Skip to content

Commit

Permalink
feat(apigateway): cors preflight support (#4211)
Browse files Browse the repository at this point in the history
* feat(apigateway): cors support (wip)

adds support for CORS preflight (OPTIONS) requests on resources.

currently supports: origin, methods, headers, credentials, status code

implemented during a live twitch stream on sep 24, 2019

* export types from cors.ts

* allow 'ANY' to be used in `allowMethods`

* add a bunch of unit tests

* document api

* support multiple origins

* add maxAge + disableCache

* document addCorsPreflight

* exposeHeaders

* doc cleanups

* reorder methods

* add integ test expectation

* defaultCorsPreflightOptions

* README

* add missing features link

* update integ test expectation

* fix compilation error

* respond with Vary if specific origin is specified

* update expectation
  • Loading branch information
Elad Ben-Israel authored and mergify[bot] committed Oct 17, 2019
1 parent 8f4a38d commit 0f06223
Show file tree
Hide file tree
Showing 11 changed files with 1,664 additions and 7 deletions.
55 changes: 55 additions & 0 deletions packages/@aws-cdk/aws-apigateway/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,61 @@ new route53.ARecord(this, 'CustomDomainAliasRecord', {
});
```

### Cross Origin Resource Sharing (CORS)

[Cross-Origin Resource Sharing (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) is a mechanism
that uses additional HTTP headers to tell browsers to give a web application
running at one origin, access to selected resources from a different origin. A
web application executes a cross-origin HTTP request when it requests a resource
that has a different origin (domain, protocol, or port) from its own.

You can add the CORS [preflight](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Preflighted_requests) OPTIONS HTTP method to any API resource via the `addCorsPreflight` method.

The following example will add an OPTIONS method to the `myResource` API resource, which
only allows GET and PUT HTTP requests from the origin https://amazon.com.

```ts
myResource.addCorsPreflight({
allowOrigins: [ 'https://amazon.com' ],
allowMethods: [ 'GET', 'PUT' ]
});
```

See the
[`CorsOptions`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-apigateway.CorsOptions.html)
API reference for a detailed list of supported configuration options.

You can specify default options for all resources within an API or a sub-tree using
`defaultCorsPreflightOptions`:


```ts
new apigateway.RestApi(this, 'api', {
defaultCorsPreflightOptions: {
allowOrigins: [ 'https://amazon.com' ]
}
});
```

This means that the construct will add a CORS preflight OPTIONS method to
**all** HTTP resources in this API gateway.

Similarly, you can specify this at the resource level:

```ts
const subtree = resource.addResource('subtree', {
defaultCorsPreflightOptions: {
allowOrigins: [ 'https://amazon.com' ]
}
});
```

This means that all resources under `subtree` (inclusive) will have a preflight
OPTIONS added to them.

See [#906](https://github.com/aws/aws-cdk/issues/906) for a list of CORS
features which are not yet supported.

----

This module is part of the [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) project.
105 changes: 105 additions & 0 deletions packages/@aws-cdk/aws-apigateway/lib/cors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { Duration } from '@aws-cdk/core';
import { ALL_METHODS } from './util';

export interface CorsOptions {
/**
* Specifies the response status code returned from the OPTIONS method.
*
* @default 204
*/
readonly statusCode?: number;

/**
* The Access-Control-Allow-Origin response header indicates whether the
* response can be shared with requesting code from the given origin.
*
* Specifies the list of origins that are allowed to make requests to this resource.
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin
*/
readonly allowOrigins: string[];

/**
* The Access-Control-Allow-Headers response header is used in response to a
* preflight request which includes the Access-Control-Request-Headers to
* indicate which HTTP headers can be used during the actual request.
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers
* @default Cors.DEFAULT_HEADERS
*/
readonly allowHeaders?: string[];

/**
* The Access-Control-Allow-Methods response header specifies the method or
* methods allowed when accessing the resource in response to a preflight request.
*
* If `ANY` is specified, it will be expanded to `Cors.ALL_METHODS`.
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods
* @default Cors.ALL_METHODS
*/
readonly allowMethods?: string[];

/**
* The Access-Control-Allow-Credentials response header tells browsers whether
* to expose the response to frontend JavaScript code when the request's
* credentials mode (Request.credentials) is "include".
*
* When a request's credentials mode (Request.credentials) is "include",
* browsers will only expose the response to frontend JavaScript code if the
* Access-Control-Allow-Credentials value is true.
*
* Credentials are cookies, authorization headers or TLS client certificates.
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials
* @default false
*/
readonly allowCredentials?: boolean;

/**
* The Access-Control-Max-Age response header indicates how long the results of
* a preflight request (that is the information contained in the
* Access-Control-Allow-Methods and Access-Control-Allow-Headers headers)
* can be cached.
*
* To disable caching altogther use `disableCache: true`.
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age
* @default - browser-specific (see reference)
*/
readonly maxAge?: Duration;

/**
* Sets Access-Control-Max-Age to -1, which means that caching is disabled.
* This option cannot be used with `maxAge`.
*
* @default - cache is enabled
*/
readonly disableCache?: boolean;

/**
* The Access-Control-Expose-Headers response header indicates which headers
* can be exposed as part of the response by listing their names.
*
* If you want clients to be able to access other headers, you have to list
* them using the Access-Control-Expose-Headers header.
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers
*
* @default - only the 6 CORS-safelisted response headers are exposed:
* Cache-Control, Content-Language, Content-Type, Expires, Last-Modified,
* Pragma
*/
readonly exposeHeaders?: string[];
}

export class Cors {
/**
* All HTTP methods.
*/
public static readonly ALL_METHODS = ALL_METHODS;

/**
* The set of default headers allowed for CORS and useful for API Gateway.
*/
public static readonly DEFAULT_HEADERS = [ 'Content-Type', 'X-Amz-Date', 'Authorization', 'X-Api-Key', 'X-Amz-Security-Token', 'X-Amz-User-Agent' ];
}
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-apigateway/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export * from './authorizer';
export * from './json-schema';
export * from './domain-name';
export * from './base-path-mapping';
export * from './cors';

// AWS::ApiGateway CloudFormation Resources:
export * from './apigateway.generated';
Expand Down

0 comments on commit 0f06223

Please sign in to comment.