Add a Get Note API

That’s a really strange error. It’s pointing to create.js:6:21. Does that show you anything?

I figured it out the issue wasn’t on create.js but on mocks get-event.json. In the documentation there isnt a “body” block so that is why it was showing the error.
Here is the original in the document

{
  "pathParameters": {
    "id": "578eb840-f70f-11e6-9d1a-1359b3b22944"
  },
  "requestContext": {
    "identity": {
      "cognitoIdentityId": "USER-SUB-1234"
    }
  }
}

Here is my edited one which worked for me.

{
  "pathParameters": {
    "id": "802ee100-a0ed-11e9-aae8-112e35b3572a"
  },
  "body": "{\"text\":\"\"}",
  "requestContext": {
    "identity": {
      "cognitoIdentityId": "USER-SUB-1234"
    }
  }
}
1 Like

Glad you figured it out.

I followed the guide to get the note created in the previous chapter.

My create function is working but the get is always returning item not found. I have created three notes so far and but get returns item not found for all three note IDs.

get-event.json

{
  "pathParameters": {
    "id": "0ac939d0-bd6f-11e9-83ec-233c3af4d792"
  },
  "requestContext": {
    "identity": {
      "cognitoIdentityId": "USER-SUB-1234"
    }
  }
}

Made a very silly mistake! in the try block inside get, I used result.item instead of result.Item. It works now! Can’t wait to continue with the rest of the guide :slight_smile:

1 Like

Two calls observed in Chrome dev-tools network explorer.

Wondered if anybody else has come across this.

When I make a call to (my equivalent of) the get Notes API I see two calls in my network explorer (Crome dev tools). (I see this on all API calls)
The fist one has an empty response but with some response headers. The second returns the data. The first call can take up to 800ms. The second 1.64 seconds.

I suspect the first call is a response from API gateway?

My question - can someone confirm if they also see two calls? And secondly - how do I get around it - if possible. It is a bit of a performance issue.

Regards

It’s quite likely the first one is the CORS request. Is it an OPTIONS request?

Yes. it is an OPTIONS request.
The only way I managed to get around it is by setting the maxAge on the headers coming back. The entry below in serverless.yml will ensure that every api call doesn’t need the OPTIONS call- only the first or if the maxAge has expired.

The second part (new) of the issue is that on the first call there is a call to the cognito service. https://cognito-identity … This is not initiated by the
await Auth.currentSession(); which I initially thought. This “I think” will use the cache to check if the current session is valid and refresh it in need.

It is initiated by the first call to the method below. (Subsequent calls do not invoke the cognito call). Any ideas on that?

To set maxAge on api method.

list:
    # Defines an HTTP API endpoint that calls the main function in list.js
    # - method: GET request
    handler: list.main
    events:
      - http:
          path: yourPath
          method: get
          cors:
            origin: '*'
            maxAge: 86400
            headers:
              - Content-Type
              - X-Amz-Date
              - Authorization
              - X-Api-Key
              - X-Amz-Security-Token
              - X-Amz-User-Agent
            allowCredentials: false
            cacheControl: 'max-age=600, s-maxage=600, proxy-revalidate'
          authorizer: aws_iam

Thanks for sharing that.

The Cognito call is managed by the AWS Amplify SDK that we are using. I vaguely recall looking at their code to see when that call gets made. But I don’t think we have control over it.

For both tests when I run serverless command I have seen “Serverless: DOTENV: Could not find .env file.” but it runs fine otherwise–getting 200 and response looks the same and the note is in dynamodb. Is this something that I need to be concerned about?

That’s fine. We add a .env file later in the guide to use environment variables.

Might not be your issue, but I was trying to run the command from the libs directory and was getting no response. Took an embarrassing amount of time to figure out.

1 Like

Ah thanks for sharing.

I’m getting this error when I run serverless invoke local --function get --path mocks/get-event.json

{
    "statusCode": 500,
    "headers": {
        "Access-Control-Allow-Origin": "*",
        "Access-Control-Allow-Credentials": true
    },
    "body": "{\"error\":\"The provided key element does not match the schema\"}"
}

Not sure what I did wrong. I copied and pasted the code right from the site. Thanks.

found the problem. In create.js code on the site it has userId and noteId but when we created the tables the i was lowercase so it should be userid and noteid. Made the change and it is working now.

Glad you figured it out. Thanks for reporting back!

I did the same! I suggest we add something about that.

1 Like

When I run
serverless invoke local --function get --path mocks/get-event.json

I get the following response:

Serverless: DOTENV: Could not find .env file.
Serverless: Bundling with Webpack...
[hardsource:2ef0fc40] Could not freeze /Users/ki/IdeaProjects/notes-app-api/get.js: Cannot read property 'hash' of undefined
{
    "statusCode": 200,
    "body": "{\"attachment\":\"hello.jpg\",\"content\":\"hello world\",\"createdAt\":1598625144607,\"noteId\":\"4a3ceaf0-e93b-11ea-b46c-3dc71670d83c\",\"userId\":\"USER-SUB-1234\"}",
    "headers": {
        "Access-Control-Allow-Origin": "*",
        "Access-Control-Allow-Credentials": true
    }
}

I understood, that the error 'Cannot read property ‘hash’ of undefined means, that the get function could not be resolved properly. But I guess I created it correctly in my serverless.yml:

# NOTE: update this with your service name
service: notes-app-api

# Create an optimized package for our functions 
package:
  individually: true

plugins:
  - serverless-bundle # Package our functions with Webpack
  - serverless-offline
  - serverless-dotenv-plugin # Load .env as environment variables

provider:
  name: aws
  runtime: nodejs12.x
  stage: prod
  region: us-east-2
  # To load environment variables externally
  # rename env.example to .env and uncomment
  # the following line. Also, make sure to not
  # commit your .env.
  #
  environment:
    tableName: notes

  # 'iamRoleStatements' defines the permission policy for the Lambda function.
  # In this case Lambda functions are granted with permissions to access DynamoDB.
  iamRoleStatements:
    - Effect: Allow
      Action:
        - dynamodb:DescribeTable
        - dynamodb:Query
        - dynamodb:Scan
        - dynamodb:GetItem
        - dynamodb:PutItem
        - dynamodb:UpdateItem
        - dynamodb:DeleteItem
      Resource: "arn:aws:dynamodb:us-east-2:*:*"

functions:
  # Defines an HTTP API endpoint that calls the main function in create.js
  # - path: url path is /notes
  # - method: POST request
  # - cors: enabled CORS (Cross-Origin Resource Sharing) for browser cross
  #     domain api call
  # - authorizer: authenticate using the AWS IAM role
  create:
    handler: create.main
    events:
      - http:
          path: notes
          method: post
          cors: true
          authorizer: aws_iam
  get:
    handler: get.main
    events:
      - http:
          path: notes/{id}
          method: get
          cors: true
          authorizer: aws_iam

anyway, if get could not be resolved there should be no reply at all – correct? But I am still receiving a 200 together with the requested object:

{
    "statusCode": 200,
    "body": "{\"attachment\":\"hello.jpg\",\"content\":\"hello world\",\"createdAt\":1598625144607,\"noteId\":\"4a3ceaf0-e93b-11ea-b46c-3dc71670d83c\",\"userId\":\"USER-SUB-1234\"}",
    "headers": {
        "Access-Control-Allow-Origin": "*",
        "Access-Control-Allow-Credentials": true
    }
}

But still I think, that it is not correct, that the error message is thrown and I would be very happy, if someone could explain, what is causing it.

Thank you – also for this awesome tutorial.

I think you can ignore that, it’s coming from Webpack. It’s related to the plugin that caches your builds to speed them up.

Thanks for this great resource.

I got stuck on the get test, with this error message:

No matching handler found for ‘get’ in ‘~/notes-app-api’. Check your service definition.

In the previous chapter, we had cd’ed into /libs, which is where I saved get.js.

I moved get.js to the project root and solved the problem.

1 Like