Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(apigateway): cors preflight support #4211

Merged
merged 23 commits into from
Oct 17, 2019
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
eladb marked this conversation as resolved.
Show resolved Hide resolved
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.
eladb marked this conversation as resolved.
Show resolved Hide resolved

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
eladb marked this conversation as resolved.
Show resolved Hide resolved
*/
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`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't specifying 0 (or less) here be an effective way to signal "I don't want no caching"? I'm not too sure the extra flag is actually so useful.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The spec doesn't say anything about 0 and we can't express -1 as a Duration.

*
* @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 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please give this class a private constructor?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

/**
* 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
Loading