How to fix the CORS error when using API Gateway with Lambda

In this article, we will learn how to fix the CORS issue using AWS Lambda with API Gateway. Here is the TLDR version.

💡
TLDR: If you're using Lambda Proxy Integration in API Gateway, you just have to do 2 things to fix CORS error
- Add default CORS Pre-flight Options to REST API
- Return Access-Control-Allow-Origin header from lambda function allowing your domain

You can read rest of the article for more details.

What is CORS?

Let's say you have your API gateway at https://<random-id>.execute-api.us-east-1.amazonaws.com  and your single-page application hosted in S3 backed by CloudFront at your domain www.your-domain.com

When you try to access the backend API through API Gateway from your react application, you may face Cross-Origin Resource Sharing(CORS) error.

CORS is a mechanism which allows a server to mention about any origin(combination of domain, scheme and port) that it want to allow a browser to load the contents from it. I strongly recommend to read this article on CORS to understand it better.

CDK Application replicating CORS issue

Let's create a simple CDK application to replicate this issue.

In below code snippet, we're creating a simple REST API with Lambda integration.

  const getMoviesFn = new NodejsFunction(this, "getMoviesFn", {
      entry: path.join(__dirname, "../lambdas", "get-movies.ts"),
      functionName: "getMoviesFn",
    });

    const api = new RestApi(this, "moviesApi", {
      restApiName: "movies-api",
    });

    const moviesIntegration = new LambdaIntegration(getMoviesFn);

    const moviesResource = api.root.addResource("movies");
    moviesResource.addMethod("GET", moviesIntegration);

Lambda function source code

This lambda function is pretty simple and it just returns the list of movies

export const handler = async (event: any) => {
  const movies = [
    {
      id: 1,
      name: "The Matrix",
    },
    {
      id: 2,
      name: "The Matrix Reloaded",
    },
    {
      id: 3,
      name: "The Matrix Revolutions",
    },
  ];

  return {
    statusCode: 200,
    body: JSON.stringify(movies),
  };
};

When I fire a GET request in Postman, I'm getting response as expected

Response in Postman

When I try to call the same API endpoint from react application using client side javascript, I'm getting below error

CORS error
CORS error

Above error is the CORS error. In plain english, the API endpoint doesn't allow requests from http://localhost:3000.

If you're using Lambda Proxy Integration, as we've used - you need to do below things

  • Add default Cors Prelight Options to REST API
  • Return additional headers from lambda function

Add Default CORS PreFlight Options to REST API:

You can add preflight options to REST API by adding property defaultCorsPreflightOptions - I've added 3 properties - allowOrigins , allowMethods and allowHeaders

const api = new RestApi(this, "moviesApi", {
      restApiName: "movies-api",
      defaultCorsPreflightOptions: {
        allowOrigins: ["http://localhost:3000"],
        allowMethods: ["OPTIONS", "GET", "POST", "PUT", "PATCH", "DELETE"],
        allowHeaders: Cors.DEFAULT_HEADERS,
      },
    });

In the above code snippet, I've added my localhost address to the list so that I can call API Gateway endpoints from my react application.


I've added few methods to be allowed. You can configure as per your needs. For example, you may want to allow read operations,  and not create/update/delete operations from other domains - you can remove POST, PUT, PATCH, DELETE from that list.

And I finally I allow the default headers.

Return additional header from lambda function

In the lambda function, you can add Access-Control-Allow-Origin header to be returned from the lambda function as shown in below code snippet.

export const handler = async (event: any) => {
  const metaData = {
    headers: {
      "Access-Control-Allow-Origin": "http://localhost:3000",
    },
  };

  return {
    ...metaData,
    statusCode: 200,
    body: JSON.stringify(movies),
  };
};

After deploying these changes, when I access the API endpoint from javascript in client side react application, I'm able to get the results as shown below

CORS error fixed
CORS error fixed

Please let me know your thoughts in comments.