Enable CORS for API Gateway or HTTP API in AWS CDK

avatar

Borislav Hadzhiev

4 min

banner

Photo from Unsplash

Table of Contents #

  1. Enable CORS for API Gateway in AWS CDK
  2. Enable CORS for HTTP API in AWS CDK - API Gateway v2

Enable CORS for API Gateway in AWS CDK #

CORS is a mechanism that allows a server to use a combination of HTTP headers to indicate from which domains, other than its own, it receives requests.

By default servers only take requests made from applications hosted on the same domain.

Setting CORS configuration is important when we access resources from a different domain.

The API Gateway service hosts APIs on the https://amazonaws.com domain, which is different from where we host our client applications, so we have to enable CORS.

The code for this article is available on GitHub

In order to demo how to set up CORS for API Gateway, I'll create a simple CDK app that consist of a single Rest API:

lib/cdk-starter-stack.ts
import * as apigateway from 'aws-cdk-lib/aws-apigateway'; import * as cdk from 'aws-cdk-lib'; export class MyCdkStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); const restApi = new apigateway.RestApi(this, 'api', { description: 'example-api', // ๐Ÿ‘‡ set up CORS defaultCorsPreflightOptions: { allowHeaders: [ 'Content-Type', 'X-Amz-Date', 'Authorization', 'X-Api-Key', ], allowMethods: ['OPTIONS', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE'], allowCredentials: true, allowOrigins: ['http://localhost:3000'], }, }); // ๐Ÿ‘‡ add a resource with 2 methods for demo purposes const todos = restApi.root.addResource('todos'); todos.addMethod('GET'); todos.addMethod('POST'); } } const app = new cdk.App(); new MyCdkStack(app, 'my-cdk-stack', { stackName: 'my-cdk-stack', env: { region: process.env.CDK_DEFAULT_REGION, account: process.env.CDK_DEFAULT_ACCOUNT, }, });
If you still use CDK version 1, switch to the cdk-v1 branch in the GitHub repository.

In the code snippet we have:

  1. Used the Rest API construct to create an API Gateway
  2. We've passed the defaultCorsPreflightOptions prop to set up CORS for all of the API's routes
  3. We've added a todos resource with GET and POST methods, just to see that the CORS configuration will apply to both.

The configuration parameters we've used for CORS are:

  • allowedHeaders - specifies which HTTP headers the frontend is allowed to use when making request to our REST API
  • allowMethods - an array of the HTTP methods our frontend is allowed to use when calling our REST API
  • allowCredentials - whether to expose the API Gateway response to the frontend when the request's credentials mode is set to include. When credentials mode is set to include, our frontend will always send user credentials (i.e. cookies, auth headers) even for CORS calls.
  • allowOrigins - an array of the origins that are allowed to make requests to our rest API. If you own a domain https://example.com that's what you'd set here.

Now I'll deploy the stack:

shell
npx aws-cdk deploy

At this point if we open the CloudFormation console, we can see that our API has been deployed:

cloudformation deployed

If we now open the OPTIONS endpoint for any of the routes, we can see that the CORS headers are applied at the Integration Response stage:

cors headers applied

If we want a more fine-grained approach to setting cors, we can do it on a per-resource basis, i.e.:

const todos = restApi.root.addResource('todos'); todos.addMethod('GET'); todos.addMethod('POST'); todos.addCorsPreflight({ allowHeaders: ['Content-Type', 'X-Amz-Date', 'Authorization', 'X-Api-Key'], allowMethods: ['OPTIONS', 'GET', 'POST', 'PUT', 'PATCH', 'DELETE'], allowCredentials: true, allowOrigins: ['http://localhost:3000'], });

However, setting CORS globally has been more common in my experience, so the defaultCorsPreflightOptions prop is what you'll want to use most of the time.

Troubleshooting CORS of API Gateway in AWS CDK #

Note that we often get cors errors when making HTTP requests to APIs, when we type in the endpoint or the HTTP method wrong.

For instance, if I make a POST request to https://api-id.aws.amazon.com/wrong-path I'll get a CORS error in the console of my browser.

The same happens if I send a request with an HTTP method that the endpoint does not support, I'll still get a CORS error.

Clean up #

To delete the stack and the provisioned resources we can run the cdk destroy command:

shell
npx aws-cdk destroy

Enable CORS for HTTP API in AWS CDK #

CORS allows us to set up a combination of HTTP headers our backend server responds with to indicate from which domains, other than its own, it receives requests.

By default servers only take requests from applications hosted on the same domain, however HTTP APIs are hosted on the https://amazonaws.com domain and our frontend application might be hosted on https://example.com, which means that we have to configure CORS.

The code for this article is available on GitHub

Let's look at an example of enabling CORS on an HTTP API in CDK:

lib/cdk-starter-stack.ts
import {CorsHttpMethod, HttpApi} from '@aws-cdk/aws-apigatewayv2-alpha'; import * as cdk from 'aws-cdk-lib'; export class CdkStarterStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); const httpApi = new HttpApi(this, 'cors-demo-api', { description: 'API for CORS demo', corsPreflight: { allowHeaders: [ 'Content-Type', 'X-Amz-Date', 'Authorization', 'X-Api-Key', ], allowMethods: [ CorsHttpMethod.OPTIONS, CorsHttpMethod.GET, CorsHttpMethod.POST, CorsHttpMethod.PUT, CorsHttpMethod.PATCH, CorsHttpMethod.DELETE, ], allowCredentials: true, allowOrigins: ['http://localhost:3000'], // ๐Ÿ‘‡ optionally cache responses to preflight requests // maxAge: cdk.Duration.minutes(5), }, }); } }
If you still use CDK version 1, switch to the cdk-v1 branch in the GitHub repository.

We created an HttpApi, where we've set the corsPreflight prop to enable CORS.

The corsPreflight object consists of the following properties:

NameDescription
allowHeaderswhich HTTP headers the frontend is allowed to use, when making requests to our HTTP API
allowMethodswhich HTTP methods the frontend is allowed to use, when making requests to our HTTP API
allowCredentialswhether credentials (cookies, auth headers) are included in the CORS requests to the HTTP API
allowOriginswhich origins are allowed to make requests to our HTTP API. If your domain is https://example.com and it needs to make requests ot the API, add it to allowOrigins.
maxAgethe duration, for which the browser will cache the response from a preflight requests. Set this if you're worried about performance. By default responses don't get cached.

Let's run the deploy command:

shell
npx aws-cdk deploy

If we look at the API named cors-demo-api, we can see that we've successfully set up CORS:

http api cors

Clean up #

To delete the resources we've provisioned, issue the destroy command:

shell
npx aws-cdk destroy
I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.

Copyright ยฉ 2023 Borislav Hadzhiev