Add a Create Note API

I think its working now

1 Like

Good to hear. What was the issue?

Iā€™m building an API / app based off the pattern from this tutorial. So the code is not 100% the same, but the response-building, serverless setup, etc is effectively identical. Since itā€™s related to the Serverless setup and API responses, this chapter feels most relevant to my issue.

Iā€™ve been running into an issue, described here at much more length, where the success responses work perfectly, but the error responses seem to get short-circuited by AWS, such that the returned error / object is not the one I build, but a generic NetworkError.

Iā€™ve been digging around on this a ton, but havenā€™t gotten to the bottom of it. If I literally just change the 200 in a response to a 500:

A) The response hits a catch on my frontend (good), and
B) The error object passed to the promise catch is just a NetworkError, with none of the information from my constructed response.

Have others run into this? Iā€™m really confused about what is causing it, and itā€™s wasting a ton of time at this point.

Thanks,

Sasha

Hmmm I would need to look into this. But you are saying that the error is just wrapped on the frontend correct? As in, if you checked the HTTP request, the response should show your Lambda function is returning?

Hi Jayair ā€“ thanks for responding!

Not sure I understand what you mean by ā€œwrapped on the frontendā€, or what you mean by checking the HTTP request. Iā€™m definitely getting successful responses to the frontend, and the Lambda logs suggest that the Lambdaā€™s getting hit on error, and executing properly (more below).

What appears to be going on is that my Lambda code is totally correct (how I know this below), but something is happening between Lambda execution and the Amplify.get() promise resolution on the frontend. As far as I know, that means the issue is with one of:

  • AWS API Gateway
  • Amplify
  • Middleware on my end

First, why I think my Lambda is executing correctly. Iā€™ve added a ton of logging on AWS, and when I hit any endpoint on my serverless API, a buildResponse function (I think modified based on one in in this tutorial) constructs a response object to return, and logs that object. The buildResponse function is called on both success and failure, and logs the object as the last step before returning the object (directly to callback(null, thatObject)).

It is, verifiably, the last step before the END RequestId log line in Cloudwatch, for both success and failure cases.

Consequently, I know that what is being logged is what is being returned. And what is logged is identical in structure between success and failure responses. Basically, this:

{
    "statusCode": 200,
    "headers": {
        "Access-Control-Allow-Origin": "*",
        "Access-Control-Allow-Credentials": true
    },
    "body": "{}"
}

An error response here differs only in that the statusCode is greater than or equal to 400. If I make that single change, I run into the ā€œbugā€.

That bug is that the frontend appears to receive, as an error in the catch rejection to the Amplify.get() promise, a generic NetworkError, with no reference to the actual object Iā€™m constructing and returning from my Lambda. As in, the above body could be an object with error text, and that object (and body) would not be in the error object returned on catch.

I have created some middleware for my app. It toggles between online and ā€œofflineā€ requests (fakes the request, so I can develop locally). But I tested this bug without the middleware (just ran a basic API.get().then(data => {}).catch(error => {}) chain), and when I hit an endpoint that returns one of the above-described constructed error objects, I just get a useless NetworkError in that catch statement ā€“ no middleware involved.

So I think I can cross that one off.

I also figured it might be the Lambda configuration, which is still my best guess, but Iā€™m all set up for Lambda-Proxy integration. Hereā€™s the basic structure of my serverless.yml file:

service: myservice

# You can pin your service to only deploy with a specific Serverless version
# Check out our docs for more details
# frameworkVersion: "=X.X.X"

provider:
  name: aws
  runtime: nodejs6.10
  region: us-west-2
  # Auto-deploy env from .env.yml file
  environment: ${file(./.env.yml):${opt:stage}}
  profile: myprofile

plugins:
  - serverless-webpack
  - serverless-offline

custom:
  webpack:
    webpackConfig: ./webpack.config.js
    includeModules: true

functions:
  projectsGetAll:
    handler: handlers/projects/getAll.handler
    events:
      - http:
          path: projects
          method: get
          cors: true
          authorizer: aws_iam

Seems like a pretty vanilla Serverless setup, and I canā€™t see any important ways that it differs from that in this tutorial.

As I pointed out in the StackOverflow post I linked to above, the AWS console confirms that Iā€™m set up for Lambda-Proxy. My API Gateway looks correctly configured.

So I think that leaves me with Amplify itself as the culprit here, but that also seems unlikely, because I havenā€™t seen a similar complaint from anyone.

So Iā€™m super confused. I guess my biggest question is whether other people have seen this, so that I could research their setups/fixes. But do you have any sense of what this might be? Have you seen this issue before? Any code/configs you might need to see to know?

Thanks!

Sasha

Hey there! Thank you for the awesome tutorial. I really appreciate it! Iā€™m stuck on this chapter and here is my error. My code is the exact same but I think I messed up the access permissions in one of the previous chapters but Iā€™m not sure where my problem lies. What should I do?

I found the error. I did not successfully execute the serverless config credentials.

1 Like

Thanks for reporting back.

Thanks for all the details. Here is what I see when I get a 500 error. This is what I see in the console.

Is that what you are seeing?

Wait a second. I just figured this one out!

I missed something really obvious, is the short of it. The error object that came back looked like this:

Error: Request failed with status code 500
    at createError (createError.js:16)
    at settle (settle.js:18)
    at XMLHttpRequest.handleLoad (xhr.js:77)

And if I did error.message, it would, sensibly, return Error: Request failed with status code 500. But, if I tried error.response, I got the constructed error message back, with the right error code. Weird, but fine, now that I know it.

Sorry to bother you, and hope thatā€™s helpful for others!

Additional important note: Amplify has some weird behavior. Despite what their docs say, adding headers in the options seems to cause misbehavior:

The above-mentioned response key only shows up when I donā€™t specify headers in the request options. In other words, this request returns an error with a response key:

API.get('my-api', '/path')

But this one returns an error without the key:

API.get('my-api', '/path', { headers: { 'Content-Type': 'application/json' } })

Very weird, but true, at least for me. Even other options are fine, but the headers option seems to mess things up.

Thanks for reporting back. Glad you figured it out.

See if this helps you with the headers.

https://aws-amplify.github.io/amplify-js/media/api_guide#custom-request-headers

Hi there, Iā€™m getting a very interesting error. So I had this whole thing up and running flawlessly. I added a few methods to my back end, but now my get, list, delete, and update methods work, however my API.post call is no longer working. In both the cli ā€œserverless invoke local --function createā€ and in the lambda test console I get:

{
    "errorMessage": "Unexpected token u in JSON at position 0",
    "errorType": "SyntaxError"
}

even when I hard code my values to take in strings. Any ideas? Thanks!

Thatā€™s usually because serverless-webpack isnā€™t transpiling things correctly. Is your webpack.config.js similar to the one in the guide?

I think I have the same problem with @ azimshaik.

serverless invoke local --function create --path mocks/create-event.json

Anything didnā€™t show up after running this invoke this.Could anyone give me any ideas for me to solve that problem ??

1 Like

I actually wrote all the same of every code on this tutorial.Should I change any place ??Like pool id ,arm id,and so onā€¦

Hmmm there shouldnā€™t be anything to change. Does it not print anything at all?

1 Like

Oh, I could get result. I actually have two cognito user pool on ohio and Virginia by mistake. So I deleted Ohio one ,and it worked.

1 Like

Oh thatā€™s good. Thanks for reporting back.

Hi, I just used this command

$ serverless invoke local --function create --path mocks/create-event.json

and got error

Cannot create property 'events' on string 'create.main'

I made sure that my create.js code is exact copy of what has been listed on the tutorial but still no luck. any pointers?

ā€œResourceNotFoundException: Requested resource not foundā€

Hi guys, Iā€™ve been following the tutorial, and i am stuck, read the q and a, and the error seems to be due to severless not being able to find my dynamo table (resource), iā€™ve gone back and forth, trying to change the regions so it matches my dynamo ā€œarn:aws:dynamodb:us-east-2:423925291108:table/notesā€

what am i doing wrong?

here is the yml file

and here is the dynamo table overview

Table name notes
Primary partition key userId (String)
Primary sort key noteId (String)
Point-in-time recovery DISABLEDEnable
Encryption DISABLED
Time to live attribute DISABLEDManage TTL
Table status Active
Creation date October 22, 2018 at 8:32:06 PM UTC+1

UTC: October 22, 2018 at 7:32:06 PM UTC

Local: October 22, 2018 at 8:32:06 PM UTC+1

Region (Ohio): October 22, 2018 at 2:32:06 PM UTC-5|

  • Provisioned read capacity units|5 (Auto Scaling Enabled)|
  • Provisioned write capacity units|5 (Auto Scaling Enabled)|
  • Last decrease time -
  • Last increase time -
  • Storage size (in bytes) 0 bytes
  • Item count 0
  • Region|US East (Ohio)
  • Amazon Resource Name (ARN)|arn:aws:dynamodb:us-east-2:423925291108:table/notes

Edit

I changed my config file (region was not set)

so i set it to:
[default]
region = us-east-2

and when i run:
aws dynamodb list-tables

logs :
{ ā€œTableNamesā€: [ā€œnotesā€ ] }

so the table does exist, but im stil getting:
ā€œResourceNotFoundException: Requested resource not foundā€