Skip to content

Closes #130 Shared API Gateway and maxAge property support for HTTP Endpoints #131

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

Merged
merged 14 commits into from
Jul 25, 2018
Merged
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 0.2.0(08.01.2017)
## Breaking Changes
The service name is added to the statemachin prefix.
The service name is added to the statemachine prefix.
This is because there is a possibility of conflict with the state machine deployed from another service without the service name.

A state machine created with version 0.1 is not inherited. Please recreate it.
Expand All @@ -18,4 +18,4 @@ A state machine created with version 0.1 is not inherited. Please recreate it.
Accidentally release(#1)

# 0.1.1(29.12.2016)
First Release
First Release
62 changes: 62 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,53 @@ stepFunctions:
definition:
```

#### Share API Gateway and API Resources

You can [share the same API Gateway](https://serverless.com/framework/docs/providers/aws/events/apigateway/#share-api-gateway-and-api-resources) between multiple projects by referencing its REST API ID and Root Resource ID in serverless.yml as follows:

```yml
service: service-name
provider:
name: aws
apiGateway:
# REST API resource ID. Default is generated by the framework
restApiId: xxxxxxxxxx
# Root resource, represent as / path
restApiRootResourceId: xxxxxxxxxx

functions:
...
```
If your application has many nested paths, you might also want to break them out into smaller services.

However, Cloudformation will throw an error if we try to generate an existing path resource. To avoid that, we reference the resource ID:

```yml
service: service-a
provider:
apiGateway:
restApiId: xxxxxxxxxx
restApiRootResourceId: xxxxxxxxxx
# List of existing resources that were created in the REST API. This is required or the stack will be conflicted
restApiResources:
/users: xxxxxxxxxx

functions:
...
```

Now we can define endpoints using existing API Gateway ressources

```yml
stepFunctions:
stateMachines:
hello:
events:
- http:
path: users/create
method: POST
```

#### Enabling CORS

To set CORS configurations for your HTTP endpoints, simply modify your event configurations as follows:
Expand Down Expand Up @@ -210,6 +257,21 @@ stepFunctions:

Configuring the cors property sets Access-Control-Allow-Origin, Access-Control-Allow-Headers, Access-Control-Allow-Methods,Access-Control-Allow-Credentials headers in the CORS preflight response.

To enable the Access-Control-Max-Age preflight response header, set the maxAge property in the cors object:

```yml
stepFunctions:
stateMachines:
SfnApiGateway:
events:
- http:
path: /playground/start
method: post
cors:
origin: '*'
maxAge: 86400
```

#### Customizing request body mapping templates

The plugin generates default body mapping templates for `application/json` and `application/x-www-form-urlencoded` content types. If you'd like to add more content types or customize the default ones, you can do so by including them in `serverless.yml`:
Expand Down
14 changes: 13 additions & 1 deletion lib/deploy/events/apiGateway/cors.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ module.exports = {
const corsMethodLogicalId = this.provider.naming
.getMethodLogicalId(resourceName, 'options');

// TODO remove once "origins" config is deprecated
let origin = config.origin;
if (config.origins && config.origins.length) {
origin = config.origins.join(',');
Expand All @@ -24,6 +25,16 @@ module.exports = {
'Access-Control-Allow-Credentials': `'${config.allowCredentials}'`,
};

// Enable CORS Max Age usage if set
if (_.has(config, 'maxAge')) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Seems that maxAge option doesn't work.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@horike37 Good catch! maxAge property issue is fixed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

cloudformation-template-update-stack.json

bildschirmfoto 2018-07-25 um 21 05 09

API Gateway Integration Response

bildschirmfoto 2018-07-25 um 21 06 37

if (_.isInteger(config.maxAge) && config.maxAge > 0) {
preflightHeaders['Access-Control-Max-Age'] = `'${config.maxAge}'`;
} else {
const errorMessage = 'maxAge should be an integer over 0';
throw new this.serverless.classes.Error(errorMessage);
}
}

if (_.includes(config.methods, 'ANY')) {
preflightHeaders['Access-Control-Allow-Methods'] =
preflightHeaders['Access-Control-Allow-Methods']
Expand All @@ -43,10 +54,11 @@ module.exports = {
RequestTemplates: {
'application/json': '{statusCode:200}',
},
ContentHandling: 'CONVERT_TO_TEXT',
IntegrationResponses: this.generateCorsIntegrationResponses(preflightHeaders),
},
ResourceId: resourceRef,
RestApiId: { Ref: this.apiGatewayRestApiLogicalId },
RestApiId: this.provider.getApiGatewayRestApiId(),
},
},
});
Expand Down
Loading