ReactJS aws blocked by CORS preflight policy

Viewed 2299

I've been trying to make a simple post request api so that my reactJS frontend can make posts, and have them populate in a table in DynamoDB. I've created the a dynamoDB table, given a lambda function permission to make requests to this table, and an API gateway to use a url to make the rest api requests. I originally did not have the intergration request in API gateway set to lambda proxy, but from the advice of aws support, I've enabled it.

This is the code I'm using in my lambda function (with the api gateway (REST API) as the trigger):

const AWS = require('aws-sdk');
const docClient = new AWS.DynamoDB.DocumentClient({region: "us-east-1"});

exports.handler = (event, context, callback) => {
    console.log("Processing...");
    
    const {name} = JSON.parse(event.body);
    
    const params = {
        TableName: "serverlessAppTest",
        Item: {
            date: Date.now(),
            name: name,
        },
    };
    
    let responseBody = {
        name: name,
    }
    
    const response = {
    statusCode: 200,
    
    headers: {
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Credentials': true,
        "Access-Control-Allow-Headers" : "Content-Type",
        "Access-Control-Allow-Methods": "OPTIONS,POST,GET"
    },
    body: JSON.stringify(responseBody)
  };
    
    docClient.put(params, function(err, data) {
        if(err){
            callback(err, null);
        } else {
            callback(null, data);
        }
    })
    console.log("response: " +JSON.stringify(response))
    return response;
};

When I try to reach the post api with the following body in the test area in lambda:

{
  "body": "{\"name\": \"Value from Lambda\"}"
}

I got a 200 OK, and the data is populated in the dynamoDB table. It also works correctly in postman, a 200 OK and data uploaded.

When I try in my reactjs code, I get the following response:

Access to XMLHttpRequest at 'https://{apivalhere}.execute-api.us-east-1.amazonaws.com/default/serverlessAPICalls' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Here's my reactjs function to make the call with a button push.

import React from "react";
import axios from "axios";

function FormHook() {
    const apiURL =
        "https://{apivalhere}.execute-api.us-east-1.amazonaws.com/default/serverlessAPICalls";

    const submitHandler = (e) => {
        e.preventDefault();
        console.log("did it");
        const headerData = {
            "Access-Control-Allow-Origin": "*",
            "Access-Control-Allow-Credentials": true,
            "Access-Control-Allow-Headers":
                "Origin, Content-Type, X-Auth-Token",
            "Access-Control-Allow-Methods":
                "GET, POST, PATCH, PUT, DELETE, OPTIONS",
        };
        axios
            .post(
                apiURL,
                {
                    name: "Hello from reactjs!",
                    message: "this is the message field.",
                },
                {
                    headers: headerData,
                }
            )
            .then((res) => {
                console.log(res);
                console.log(res.data);
            })
            .catch((err) => {
                console.log(err);
            });
    };

    return (
        <div>
            <form onSubmit={submitHandler}>
                <button type="submit">Send</button>
            </form>
        </div>
    );
}
export default FormHook;

I've gone through about a dozen or more docs on stackoverflow and aws support trying to resolve this issue, and I keep getting blocked with this cors issue. I've tried specifically stating "application/json" in my headers, along with specifically allowing 'localhost:3000', then tried '*' in the Control Allow Origin for both the lambda node.js code, and reactjs post method. I'm at a complete loss at what I could do to fix this and could use some help. I'm relatively new with making my own functions to handle api requests, so any guidance or suggestions would be much appreciated.

edit: I received the same CORS error with the following as well.

import React from "react";
import axios from "axios";

function FormHook() {
    const apiURL =
        "https://{apivalhere}.execute-api.us-east-1.amazonaws.com/default/serverlessAPICalls";

    const submitHandler = (e) => {
        e.preventDefault();
        console.log("did it");
        axios
            .post(
                apiURL,
                {
                    name: "Hello from reactjs!",
                    message: "this is the message field.",
                },
            )
            .then((res) => {
                console.log(res);
                console.log(res.data);
            })
            .catch((err) => {
                console.log(err);
            });
    };

    return (
        <div>
            <form onSubmit={submitHandler}>
                <button type="submit">Send</button>
            </form>
        </div>
    );
}
export default FormHook;
2 Answers

For my setup in particular, the issue was in my api gateway configuration and process in lambda. I was not handling the OPTIONS request, which was causing the bad gateway (502 error). To fix this, in the api gateway I'd set an OPTIONS methods integration request type to MOCK. This causes the api gateway to just chuck out whatever OPTIONS request it gets, and allows the following post request to come through.

This is definitely not best practice and will be updated to handle the OPTIONS request more gracefully, but it's working now.

This great article explains the solution: AWS CORS Policy with React

You have to go through to every detail, I also read it several times to realise how to set the headers for every request right.

Related