Call the Create API

Should cors headers be set anywhere in the React app?

No there isn’t any on the React side. But this 403 error means that, the request isn’t getting to the Lambda functions. It is failing at the API Gateway level. These are a bit trickier to debug.

Here is how to see what the actual error is. I’m going to add this to the guide soon. But you can use it to debug it right away.

Add the following block at the bottom of your serverless.yml and re-deploy it using serverless deploy.

resources:
  Resources:
    GatewayResponseDefault4XX:
      Type: 'AWS::ApiGateway::GatewayResponse'
      Properties:
        ResponseParameters:
           gatewayresponse.header.Access-Control-Allow-Origin: "'*'"
           gatewayresponse.header.Access-Control-Allow-Headers: "'*'"
        ResponseType: DEFAULT_4XX
        RestApiId:
          Ref: 'ApiGatewayRestApi'

The reason we need to do this because when API Gateway fails, it doesn’t get to our Lambda function. The Lambda function sets the CORS headers. So in this case you get failures that also look like CORS errors. When in reality they are just regular errors without the CORS headers. The above block adds a resource to API Gateway telling it to set the CORS headers for any 4XX failures.

Thanks @jayair I added it but then I got the same CORS message for 502 instead so did the same in GatewayResponse for default 5XX. That solved the CORS message showing up but I’m still getting 502 and there’s nothing showing up in the CloudWatch logs…

I can call the POST method and create a new note if I do serverless invoke --function create --path mocks/create-note.json in the terminal. But I’m getting 502 when I try to do it in React. Any idea what’s going on?

Hmm 500 errors are a part of your code. So you should be able to console.log what is being returned.

@jayair

What should I be expecting to be returned from this:

createNote(note) {
  return API.post("notes", "/notes", {
    body: note
  });
} 

The table does get updated, but I am not receiving the result of the success() function in my handler.
For my project, if I do these console.logs():

   createContact(contact) {
        const result = API.post('contacts', '/contacts', {
            body: contact
        }).then((data) => console.log('Then', data))
        console.log('Create: ', result)
        return result
    }

the promise stored to result:

[[PromiseStatus]]:"resolved"
[[PromiseValue]]:undefined

data:
Then

I would expect that data would at least be undefined here.
What I would like, is to retrieve the newly created item. Is that possible here?

These are promises, so you would need an await if you want the result after it resolves.

    const result = await API.post('contacts', '/contacts',...
1 Like

Thanks. I am a little new to promises, but I think I am figuring out how they are working.

1 Like

We are new to AWS serverless stack and tried our hands on to build the notes app using the documentation. We are at: https://serverless-stack.com/chapters/call-the-create-api.html and stuck with getting response
{message: “Missing Authentication Token”}
with 403 status code
on submitting notes at http://localhost:3000/notes/new

We have followed each and every step carefully.
Please help

Have you tested the API with the CLI?

Hello,
I was getting a CORS error so I turned off my CORS support in chrome, now I am getting a 403 error but It seems like something is connecting. Under the network tab in dev tools, there seems to be 2 calls to the back-end. the first one is a OPTIONS request method which goes through with a 200 status code but immediately after that there is the POST request that returns a 403 error. I will include the headers for both. Hopefully you can point me in the right directions, as far as where to begin debugging… Everything up until now has worked fine. Just to be clear, both of these calls happen immediately when I try to test post a note. Thanks for your help!

Anthony

(some of the link have spaces added by me because I am limited to the number of links being a new user and the system would not let me post unless they were not active)
THE FIRST CALL:

General
Request URL: https://57m9facagg.execute-api.us-east-1.amazonaws.com/prod/notes
Request Method: OPTIONS
Status Code: 200
Remote Address: 99.84.41.38:443
Referrer Policy: no-referrer-when-downgrade

Response Headers
access-control-allow-credentials: false
access-control-allow-headers: Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent
access-control-allow-methods: OPTIONS,GET,POST
access-control-allow-origin: h ttp://localhost:3000
content-length: 1
content-type: application/json
date: Sun, 26 May 2019 13:39:39 GMT
status: 200
via: 1.1 831e7b98ff065d26405d36a8a652162c.cloudfront.ne t (CloudFront)
x-amz-apigw-id: aSyMWGTyoAMF90Q=
x-amz-cf-id: qEnze9nU-uJ9fPzsfSKMA3z9aWg_gUgf1aDJtt64oKsFoyZLCkkBIw==
x-amzn-requestid: b5de0903-7fbb-11e9-9fde-f37742a70157
x-cache: Miss from cloudfront

Request Headers
Provisional headers are shown
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: POST
Origin: h ttp://localhost:3000
Referer: h ttp://localhost:3000/notes/new
User-Agent: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Mobile Safari/537.36

THE SECOND CALL:

General

Request URL: https://57m9facagg.execute-api.us-east-1.amazonaws.com/prod/notes
Request Method: POST
Status Code: 403
Remote Address: 99.84.41.38:443
Referrer Policy: no-referrer-when-downgrade

Response Headers
access-control-allow-headers: *
access-control-allow-origin: *
content-length: 42
content-type: application/json
date: Sun, 26 May 2019 13:39:39 GMT
status: 403
via: 1.1 831e7b98ff065d26405d36a8a652162c.cloudfront.ne t (CloudFront)
x-amz-apigw-id: aSyMWGIsoAMFZVA=
x-amz-cf-id: Rdu3BCxIgHO9GubffmABJwhPhV0q6IyDb-ZdUYDd_jkFHIXVZtzFjQ==
x-amzn-errortype: MissingAuthenticationTokenException
x-amzn-requestid: b5e47207-7fbb-11e9-a301-5bae2ffb07de
x-cache: Error from cloudfront

Request Headers
Provisional headers are shown
Accept: application/json, text/plain, /
Content-Type: application/json; charset=UTF-8
Origin: h ttp://localhost:3000
Referer: h ttp://localhost:3000/notes/new
User-Agent: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Mobile Safari/537.36

Request Payload
{content: “SDFSDF”}
content: “SDFSDF”

Never mind… I figured it out.

I was using the wrong pool number. in the config file…

Thanks and keep up the good work on the tutorial!!

1 Like

Glad you figured it out. These issues are hard to debug.

Hi there! I’m on stage of Calling the create API. However when I call it, it returns “Error: Request failed with status code 404”. I have checked the S3 bucket and images are being uploaded to S3 normally, however the DynamoDB table doesn’t get updated. I tried to execute the create mock and it works fine. I’m stuck. Anybody has any ideas of this?


Note: Instead of notes I have recipes

That URL in the console does not look right. Any idea where that is coming from?

Edit: Just noticed you figured it out in the other thread.

Thanks for these tutorials, I had been trying to teach myself and was getting there but this is much faster!

I’m getting an alert when I submit the create button. “Error: Request failed with status code 404”. I searched the comments and found Kissa’s 404 error but she said in another discussion that it was due to her region and url being swapped in her config file. I have double checked all the info in the config file matches what is in AWS, is in the right fields and even looks the same as the examples you provided in each of those sections. Went back to the last point it was working and redid the steps up to this one and it still is giving me a 404 error.

Not sure if this helps but 2 things that went wrong up to this point. I initially was in the ‘us-east-2’ region before I realized how often you need regions or that regions could even be different in different services and to maintain my sanity I went back and deleted the first S3 bucket that I had made in that region and moved it to ‘us-east-1’ (I have verified that is where mine is.) But I had restarted from scratch and redid all the steps through that point so I don’t know if somehow that old bucket has thrown a monkey wrench in the works. Another kerfuffle I ran into was with the formatting of the Windows command line in the “Test the API’s” chapter. I didn’t read past the mac code to see that you provided the windows code after it and ended up following a bunch of the suggestions like rolling back my serverless framework version and redeploying it a couple of times before I realized that wasn’t the issue and went back to the current version. Other than that, everything has looked identical to what you show as the expected result. Sorry for the long-winded post, just want to make sure I’m giving you any pertinent information. Here’s my git repos:


Help me Obi-wan Kenobi! You’re my only help!

I’m not totally sure whats going on but any idea why the https:// is missing here?

That was it, thanks! Can’t believe I missed that, especially since Kissa’s 404 had to do with her config file as well. ah well…tired eyes are the devil in coding.

1 Like

Hi, I’ve completed the tutorial and am now trying to customize for my own app. I’m trying to get modify the createNote API so that I can add an array to DynamoDB (ideally a mix of strings and numbers with labels, but will settle for just an array of strings). Can you let me know what the purpose is of this function:

function createNote(note) {
  return API.post("notes", "/notes", {
    body: note
  });

Here’s my attempt but I can’t get it to add anything besides the text of the “note box” to Dynamo.

import React, { useState } from "react";
import { FormGroup, FormControl, ControlLabel } from "react-bootstrap";
import LoaderButton from "../components/LoaderButton";
import config from "../config";
import "./NewAdu.css";
import { API } from "aws-amplify";
import { s3Upload } from "../libs/awsLib";

export default function NewAdu(props) {
  const [content, setContent] = useState("");
  const [purchprice, setPurchprice] = useState("");
  const [purchdate, setPurchdate] = useState("");
  const [isLoading, setIsLoading] = useState(false);

  function validateForm() {
    return content.length > 0 && purchprice.length > 0 && purchdate.length > 0;
  }

  async function handleSubmit(event) {
    event.preventDefault();

    setIsLoading(true);

    try {
      await createAdu({ content, purchprice, purchdate });
      props.history.push("/");
    } catch (e) {
      alert(e);
      setIsLoading(false);
    }
  }

  function createAdu(note) {
    return API.post("notes", "/notes", {
      body: note
    });
  }

  return (
    <div className="NewAdu">
      <form onSubmit={handleSubmit}>
        <FormGroup controlId="content">
          <FormControl
            autoFocus
            value={content}
            componentClass="textarea"
            onChange={e => setContent(e.target.value)}
          />
        </FormGroup>
        <FormGroup controlId="purchprice" bsSize="large">
          <ControlLabel>Purchase Price</ControlLabel>
          <FormControl
            type="number"
            value={purchprice}
            onChange={e => setPurchprice(e.target.value)}
          />
        </FormGroup>
        <FormGroup controlId="purchdate" bsSize="large">
          <ControlLabel>Purchase Date</ControlLabel>
          <FormControl
            type="date"
            value={purchdate}
            onChange={e => setPurchdate(e.target.value)}
          />
        </FormGroup>
        <LoaderButton
          block
          type="submit"
          bsSize="large"
          bsStyle="primary"
          isLoading={isLoading}
          disabled={!validateForm()}
        >
          Create
        </LoaderButton>
      </form>
    </div>
  );
}

In case anyone else is a beginner and looking to do the same, you need to do the above and then also modify create.js to actually put these items to dynamo.

1 Like

Ah I see. Thanks for sharing!