Add a Get Note API

I’m a relative noob on all this (aws, serverless), but this might be one of the absolute best tutorials i ever came across. On any topic that is. I made heaps of progress on aws, react, bootstrap, and serverless with this.

Me and my bud have been trying to set up a serverless backend with both a web frontend, and an iOS native swift client.
The latter would have to use a swift aws api-gateway sdk which is generated from the aws console. But it seems that this function is unaware of the path parameter (being {id} in this case) the API endpoint needs. So for example, when i generate the SDK for the notes app in this tutorial after deploying the functions to aws with serverless deploy, the getNote function in the generated swift sdk doesn’t take an id parameter.
Turns out path parameters have to be explicitely defined in serverless.yml for the SDK functions to be properly generated, including the path parameters as its function parameters. This might be a new addition since this tutorial was written, and if it is i’m sorry. But the function setup in serverless.yml for iOS SDK generation to work properly would be as follows:

 - http:
          path: notes/{id}
          method: get
          cors: true
          authorizer: aws_iam
                               id: true

So the request part and below are new, they define the path parameters. For interaction with a react frontend, obviously explicitely defining this doesn’t seem to be necessary, but for the iOS SDK turns out it is. Oh well, that’s AWS for ya!

1 Like

I got this issue on running get-event.json. Could anyone find out what is this?

    $ serverless invoke local --function get --path mocks/get-event.json
  Serverless Error ---------------------------------------
  Events for "get" must be an array, not an object

Hey guys, sorry I got the solution for my above mentioned issued. It is because of the space between - and http in serverless.yml

    handler: get.main
      - http:
          path: notes/{id}
          method: get
          cors: true
          authorizer: aws_iam
1 Like

Thanks for the kind words!

And thanks for the feedback. I’ll add a note to the chapter with this!

Glad you figured it out! Thanks for reporting back.

I am getting the following error. I have checked and checked I cannot see what I did wrong. I can create an event just cant get it.

C:\Users\activated\myfitnessbook-app-api>serverless invoke local --function create --path mocks\get-event.json
Serverless: Bundling with Webpack...
Time: 620ms
Built at: 07/07/2019 9:04:46 PM
        Asset      Size  Chunks             Chunk Names
    create.js  10.1 KiB  create  [emitted]  create  7.23 KiB  create  [emitted]  create
Entrypoint create = create.js
[./create.js] 2.37 KiB {create} [built]
[./libs/dynamodb-lib.js] 468 bytes {create} [built]
[./libs/response-lib.js] 762 bytes {create} [built]
[aws-sdk] external "aws-sdk" 42 bytes {create} [built]
[babel-runtime/core-js/json/stringify] external "babel-runtime/core-js/json/stringify" 42 bytes {create} [built]
[babel-runtime/helpers/asyncToGenerator] external "babel-runtime/helpers/asyncToGenerator" 42 bytes {create} [built]
[babel-runtime/regenerator] external "babel-runtime/regenerator" 42 bytes {create} [built]
[source-map-support/register] external "source-map-support/register" 42 bytes {create} [built]
[uuid] external "uuid" 42 bytes {create} [built]
    "errorMessage": "Unexpected token u in JSON at position 0",
    "errorType": "SyntaxError",
    "stackTrace": [
        "SyntaxError: Unexpected token u in JSON at position 0",
        "    at JSON.parse (<anonymous>)",
        "    at _callee$ (C:\\Users\\activated\\myfitnessbook-app-api\\.webpack\\service\\webpack:\\create.js:6:21)",
        "    at tryCatch (C:\\Users\\activated\\myfitnessbook-app-api\\node_modules\\regenerator-runtime\\runtime.js:62:40)",
        "    at Generator.invoke [as _invoke] (C:\\Users\\activated\\myfitnessbook-app-api\\node_modules\\regenerator-runtime\\runtime.js:296:22)",
        "    at Generator.prototype.(anonymous function) [as next] (C:\\Users\\activated\\myfitnessbook-app-api\\node_modules\\regenerator-runtime\\runtime.js:114:21)",
        "    at step (C:\\Users\\activated\\myfitnessbook-app-api\\node_modules\\babel-runtime\\helpers\\asyncToGenerator.js:17:30)",
        "    at C:\\Users\\activated\\myfitnessbook-app-api\\node_modules\\babel-runtime\\helpers\\asyncToGenerator.js:35:14",
        "    at new Promise (<anonymous>)",
        "    at new F (C:\\Users\\activated\\myfitnessbook-app-api\\node_modules\\core-js\\library\\modules\\_export.js:35:28)",
        "    at C:\\Users\\activated\\myfitnessbook-app-api\\node_modules\\babel-runtime\\helpers\\asyncToGenerator.js:14:12",
        "    at main (C:\\Users\\activated\\myfitnessbook-app-api\\.webpack\\service\\create.js:153:17)",
        "    at BbPromise (C:\\Users\\activated\\AppData\\Roaming\\npm\\node_modules\\serverless\\lib\\plugins\\aws\\invokeLocal\\index.js:628:30)",
        "    at Promise._execute (C:\\Users\\activated\\AppData\\Roaming\\npm\\node_modules\\serverless\\node_modules\\bluebird\\js\\release\\debuggability.js:313:9)",
        "    at Promise._resolveFromExecutor (C:\\Users\\activated\\AppData\\Roaming\\npm\\node_modules\\serverless\\node_modules\\bluebird\\js\\release\\promise.js:488:18)",
        "    at new Promise (C:\\Users\\activated\\AppData\\Roaming\\npm\\node_modules\\serverless\\node_modules\\bluebird\\js\\release\\promise.js:79:10)",
        "    at AwsInvokeLocal.invokeLocalNodeJs (C:\\Users\\activated\\AppData\\Roaming\\npm\\node_modules\\serverless\\lib\\plugins\\aws\\invokeLocal\\index.js:582:12)",
        "    at AwsInvokeLocal.invokeLocal (C:\\Users\\activated\\AppData\\Roaming\\npm\\node_modules\\serverless\\lib\\plugins\\aws\\invokeLocal\\index.js:151:19)",
        "    at AwsInvokeLocal.tryCatcher (C:\\Users\\activated\\AppData\\Roaming\\npm\\node_modules\\serverless\\node_modules\\bluebird\\js\\release\\util.js:16:23)",
        "    at Promise._settlePromiseFromHandler (C:\\Users\\activated\\AppData\\Roaming\\npm\\node_modules\\serverless\\node_modules\\bluebird\\js\\release\\promise.js:517:31)",
        "    at Promise._settlePromise (C:\\Users\\activated\\AppData\\Roaming\\npm\\node_modules\\serverless\\node_modules\\bluebird\\js\\release\\promise.js:574:18)",
        "    at Promise._settlePromiseCtx (C:\\Users\\activated\\AppData\\Roaming\\npm\\node_modules\\serverless\\node_modules\\bluebird\\js\\release\\promise.js:611:10)",
        "    at _drainQueueStep (C:\\Users\\activated\\AppData\\Roaming\\npm\\node_modules\\serverless\\node_modules\\bluebird\\js\\release\\async.js:142:12)",
        "    at _drainQueue (C:\\Users\\activated\\AppData\\Roaming\\npm\\node_modules\\serverless\\node_modules\\bluebird\\js\\release\\async.js:131:9)",
        "    at Async._drainQueues (C:\\Users\\activated\\AppData\\Roaming\\npm\\node_modules\\serverless\\node_modules\\bluebird\\js\\release\\async.js:147:5)",
        "    at Immediate.Async.drainQueues (C:\\Users\\activated\\AppData\\Roaming\\npm\\node_modules\\serverless\\node_modules\\bluebird\\js\\release\\async.js:17:14)",
        "    at runCallback (timers.js:705:18)",
        "    at tryOnImmediate (timers.js:676:5)",
        "    at processImmediate (timers.js:658:5)",
        "    at process.topLevelDomainCallback (domain.js:126:23)"


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.


  "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.


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.

    # Defines an HTTP API endpoint that calls the main function in list.js
    # - method: GET request
    handler: list.main
      - http:
          path: yourPath
          method: get
            origin: '*'
            maxAge: 86400
              - 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.