A grunt plugin to easily configure and deploy AWS API Gateway.
AWS API Gateway configuration through the web console takes lot of mouse clicks and is error prone. This grunt plugin allows you to script and automatically deploy your API Gateway configuration.
npm install grunt-aws-apigateway --save-dev
The following usage example could look a bit verbose at a first glance. However, AWS API Gateway setup is pretty complex and the following resources
structure tries to map as much close as possible the AWS API, in order to provide the same degree of flexibility.
grunt.initConfig({
apigateway_deploy: {
options: {
accessKeyId: "key",
secretAccessKey: "secret",
region: "us-east-1"
},
default: {
restApiId: "xxx",
deployment: {
stageName: "prod"
},
resources: {
"/users": {
methods: {
GET: {
integration: {
type: "AWS",
uri: "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:xxx:function:getUsers/invocations",
integrationHttpMethod: "POST",
requestTemplates: {
"application/json": JSON.stringify({
"filter": "$input.params('filter')"
})
}
},
responses: {
200: {
// Pass-through
responseModels: {
"application/json": "Empty"
}
},
400: {
selectionPattern: "error code: 400",
responseTemplates: {
"application/json": JSON.stringify({"error": "$input.path('$.errorMessage')"})
}
}
}
}
}
}
}
}
}
});
grunt.loadNpmTasks('grunt-aws-apigateway');
grunt.registerTask(
"deploy-api",
"Deploy the API Gateway config",
["apigateway_deploy"]
);
What you can do:
- Create API resources
- Configure resource's Method Request, Integration Request, Method Response, Integration Response
- Deploy API changes to a stage
What you can't do:
- Create models
One time configuration you should do by hand:
- Create a new API
- Create stages (once created, the plugin will deploy the API to the configured stage)
- Create an IAM user with the policy required to deploy your API
- Add permission to each Lambda function will get invoked by API Gateway (in case you're integration API Gateway with AWS Lambda functions). Troubleshooting section explains how to do it.
NOTE: to ease the development of this plugin, each run deletes all resources and re-creates them. This means that it doesn't apply differential changes and if you've already created some resources that are not part of plugin configuration, you will loose it at the first run. In other words, make sure the plugin configuration contains all resources of your API.
The plugin config is made of 3 required properties:
restApiId
(your API Gateway id)resources
deployment
The resources
property contains the configuration of all your API Resources. Resources are organized in a tree, the path must start with a /
and each resource's full path is built concatenating together all parent resources paths.
Example - create /tweets/trends
resource:
{
resources: {
"/tweets": {
"/trends": {}
}
}
}
Each resource can have zero or more methods. For each method you must define a request and response integration (ie. a AWS Lambda function).
Example - add GET
method to /tweets/trends
resource:
{
resources: {
"/tweets": {
"/trends": {
methods: {
GET: {
authorizationType: "NONE",
apiKeyRequired: false,
integration: { /* Integration Request config */ },
responses: { /* Integration Response config */ }
}
}
}
}
}
}
The resource's Integration Request config must contain the integration type
and uri
, along with other optional settings (ie. requestTemplates
).
Example - integrate a lambda function to GET /tweets/trends
:
integration: {
type: "AWS",
uri: "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:xxx:function:getUsers/invocations",
integrationHttpMethod: "POST", // Lambda functions must be called with a POST
credentials: undefined,
requestParameters: {},
cacheNamespace: undefined,
cacheKeyParameters: [],
requestTemplates: {
"application/json": JSON.stringify({
"filter": "$input.params('filter')"
})
}
}
The resource's Integration Response config is a map whose keys are the status codes, and the value is the configuration for each status code.
Example - integrate 200
and 400
response codes:
responses: {
200: {
responseModels: {
"application/json": "Empty"
},
responseParameters: {},
responseTemplates: {}
},
400: {
selectionPattern: "error code: 400",
responseParameters: {},
responseTemplates: {
"application/json": JSON.stringify({"error": "$input.path('$.errorMessage')"})
}
}
}
The last step of apigateway_deploy
is to deploy all the changes to a stage. The configuration of this phase is made through the deployment
property. stageName
is the only required property.
{
deployment: {
stageName: "prod",
cacheClusterEnabled: false,
cacheClusterSize: "1G"
description: "",
stageDescription: "",
variables: []
}
}
AWS region where you would like to deploy your API.
If you prefer to use hardcoded AWS credentials, you should both set accessKeyId
and secretAccessKey
.
If you prefer to use AWS credentials stored in a JSON file, you should set the JSON file path here.
If you prefer to use a specific AWS credentials profile you can set it here.
This error occurs when you didn't add permission to run the Lambda function from the API Gateway service. To fix it, run the following command:
$ aws lambda add-permission --function-name "<your function name>" --action "lambda:InvokeFunction" --principal "apigateway.amazonaws.com" --source-arn "<your api gateway endpoint arn>" --statement-id "522028352"
Example:
aws lambda add-permission --function-name "getUsers" --action "lambda:InvokeFunction" --principal "apigateway.amazonaws.com" --source-arn "arn:aws:execute-api:us-east-1:123456789:abcdefg/*/GET/users" --statement-id "522028352"
You're very welcome to contribute to this pluging, in case you spot any bug, or to add some missing features (ie. create models). Please do your best to:
- Keep the coding style
- Keep your code as much clean (and readable) as possible
MIT