How to enable CORS on API Gateway with Lambda proxy integration?
When building single-page applications (SPA), you will sooner or later stumble upon Cross-Origin Resource Sharing (CORS). In short, a browser does only allow requests to the same same origin (domain, protocol and port), that was used for the initial request by default.
However, a typical Serverless application uses CloudFront and S3 to deliver the static files like .html
, .css
, and .js
and an API Gateway acting as the front door for the backend. In that case, the hostname to access CloudFront - for example, myapp.com
- is different than the hostname to access the API Gateway - for example, api.myapp.com
. Therefore, a browser would block requests to api.myapp.com
. To allow the SPA to access the API Gateway, you need to implement CORS on the backend. This article explains how to do so when using the API Gateway with Lambda proxy integration.
The proxy integration is an easy way to configure the API Gateway. It starts with the gateway forwarding all parts of an HTTP request to the Lambda function. Next, the Lambda function returns all details of an HTTP response. No complicated configuration and data mapping needed on the API Gateway.
Three steps are necessary to enable CORS for the backend when using the Lambda proxy integration:
- Implement adding CORS headers with the Lambda function
- Add static response for OPTIONS requests
- Add CORS headers to server-side errors
You will learn more about those three steps in the following.
Implement adding CORS headers with the Lambda function
When configuring the proxy integration on the API Gateway, the Lambda function needs to return a response in a specific format. The following code snippet shows how to add the necessary CORS header Access-Control-Allow-Origin
.
exports.handler = async (event) => { |
Remember to add the Access-Control-Allow-Origin
to all Lambda functions.
Add static response for OPTIONS requests
Additionally, the browser sends a so called CORS preflight requests (HTTP method OPTIONS
) to each API resource to check for CORS configuration. Therefore, you need to make sure that the API Gateway answers OPTIONS
requests for all resources that should be accessed by the SPA. To simplify the configuration, creating a proxy resource allows you to add an OPTIONS
method to all resources at once. The following Terraform configuration snippet shows how to create a proxy resource to answer the OPTIONS
requests for all API resources.
resource "aws_api_gateway_rest_api" "backend" { |
That’s it. The API Gateway will answer all CORS related OPTIONS
requests now.
Add CORS headers to server-side errors
Finally, you need to make sure that the API Gateway is also adding the CORS headers in case of server-side errors. Why is that important? For example, when the API Gateway fails to invoke your Lambda function, it will return a server-side error. In that case, the Lambda function cannot add the necessary Access-Control-Allow-Origin
header to the response. Therefore, you need to configure the API Gateway to add the CORS header for server-side errors, as illustrated in the following Terraform configuration snippet.
resource "aws_api_gateway_gateway_response" "response_4xx" { |
That’s it. You have successfully enabled CORS for your backend.
Summary
When using the Lambda proxy integration, the following steps are necessary to enable CORS on the backend of your Serverless application.
- Implement adding CORS headers with the Lambda function
- Add static response for OPTIONS requests
- Add CORS headers to server-side errors
By the way, you could also avoid CORS entirely by running the API Gateway behind the same domain as your SPA. For example, by configuring CloudFront to route requests to myapp.com/api/*
to a regional API Gateway while routing everything else to an S3 bucket.
Further reading
- Article AWS Account Structure: Think twice before using AWS Organizations
- Article Terraform, can you keep a secret?
- Article How to avoid S3 data leaks?
- Tag lambda
- Tag apigateway
- Tag serverless