AWS API Gateway is a cloud scale API service that is an integration point for AWS services or third party services. The service is very easy to use. First define an OpenAPI specification, then define integrations for the OpenAPI specification and deploy the specification using CloudFormation. API Gateway supports five types of integrations:
- mock: for integration with API Gateway without invoking any backend
- aws: for integrating with AWS services, while allowing transformations
- aws_proxy: for integrating with AWS Lambda
- http: for integrating with HTTP backends, while allowing transformations
- http_proxy: for integrating with HTTP backends
We’ll look at all of the integration types today
aws-cfn-update
"AWS API Gateway makes it easy for developers to create, publish, maintain and monitor secure APIs at any scale", according
to the official documentation. Although this is true, it is far from trivial to
create an API using CloudFormation templates. The CloudFormation template will contain both an OpenAPI specification, AWS extensions to the
OpenAPI specification and the AWS infrastructure specification to create.
To make developing APIs easier, binx.io created a tool called aws-cfn-update.
The utility updates CloudFormation templates and merges OpenAPI specification with the AWS extensions and then merges the
result into the CloudFormation templates. The utility also supports merging lambda code into CloudFormation, if the code does
not exceed 4000 characters and the language is either Python or Node.js. The utility makes it possible to create projects that
separates specifications and allows for maintainable API projects.
Example Project
The example project shows a project that consists
of a number of project that shows how to create and use each integration type.
OpenAPI specification
API Gateway supports both OpenAPI v2.0 aka. ‘swagger’,
and OpenAPI v3.0. The OpenAPI Specification makes it
easy to define resources, methods and responses for the API. Project 01-swagger
shows an example project that only creates the API Gateway Method requests. There are no integrations configured in this project.
The OpenAPI specification is available in the directory swagger/swagger.yaml
.
Type:
- make merge-swagger: to merge the OpenAPI specification with CloudFormation
- make deploy: to deploy the project
- make delete: to delete the project
Mock Integration
Project 02-mock-integration shows
how to setup ‘mock’ integrations. Mock integrations generate API responses from API Gateway directly, without the need for an integration backend.
Mock integrations are great to generate static responses like CORS responses for a POST request. The AWS extensions to the OpenAPI specification
are in the directory swagger/aws-extensions.yaml
An example mock integration:
x-amazon-apigateway-integration:
responses:
default:
statusCode: '200'
responseParameters:
method.response.header.Content-Type: "'application/json'"
method.response.header.Access-Control-Allow-Headers : "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
method.response.header.Access-Control-Allow-Methods : "'*'"
method.response.header.Access-Control-Allow-Origin : "'*'"
responseTemplates:
application/json: |-
[{
"id": 1,
"name": "Superman"
},
{
"id": 2,
"name": "Batman"
}]
passthroughBehavior: when_no_match
requestTemplates:
application/json: |-
{
"statusCode": 200
}
type: mock
The mock responds with a HTTP ‘200’ and a list of heroes in JSON format.
HTTP Integration
Project 03-http-integration shows
how to setup ‘http’ integrations. Http integrations are useful when an API method must be integrated with a HTTP endpoint like eg. a utility
service on the Internet or a Http service in the VPC. An example HTTP integration:
x-amazon-apigateway-integration:
responses:
default:
statusCode: '200'
responseParameters:
method.response.header.Content-Type: "'application/json'"
method.response.header.Access-Control-Allow-Headers : "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
method.response.header.Access-Control-Allow-Methods : "'*'"
method.response.header.Access-Control-Allow-Origin : "'*'"
passthroughBehavior: when_no_match
uri: 'https://httpbin.org/anything'
httpMethod: GET
type: http_proxy
The http integration calls httpbin.org with a ‘GET’ and responds with a HTTP ‘200’. The integration type
can be either ‘http_proxy’ or ‘http’.
AWS Proxy (Lambda) Integration
Project 04-lambda-integration shows
how to setup ‘aws_proxy’ integrations. Creating a lambda is more involved. When using Python, the lambda can be inlined in the CloudFormation
template when code is less than 4kB. To support good programming practices, the code should be testable and separated from the CloudFormation template.
The utility aws-cfn-update can merge the lambda code with the CloudFormation template when
the stack should be deployed. For lambda integration, API Gateway must have a role in order to invoke the lambda:
APIGatewayInvokeLambdaRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: apigateway.amazonaws.com
Action: sts:AssumeRole
Condition: {}
Path: /
Policies:
- PolicyName: ApiGateway
PolicyDocument:
Statement:
- Effect: Allow
Action:
- lambda:InvokeFunction
Resource:
- '*'
The ‘aws_proxy’ integration:
x-amazon-apigateway-integration:
responses: {}
uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${LambdaHandler.Arn}/invocations
credentials: !GetAtt APIGatewayInvokeLambdaRole.Arn
passthroughBehavior: when_no_match
httpMethod: POST
type: aws_proxy
Note that the ‘aws_proxy’ integration points to the ‘arn’ of the lambda. The credentials for API Gateway is defined by the
‘APIGatewayInvokeLambdaRole’.
AWS Service Integration
Project 05-aws-service-integration shows
how to setup ‘aws’ service integration. API gateway can invoke the API of AWS services like eg. DynamoDB. API Gateway must have
a role in order to invoke DynamoDB:
APIGatewayRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: apigateway.amazonaws.com
Action: sts:AssumeRole
Condition: {}
Path: /
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess
The ‘aws’ integration:
x-amazon-apigateway-integration:
credentials: !GetAtt APIGatewayRole.Arn
uri: !Sub "arn:aws:apigateway:${AWS::Region}:dynamodb:action/Scan"
responses:
default:
statusCode: "200"
responseTemplates:
application/json: |-
[
#foreach ($item in $input.path('$.Items'))
{
"id": "$item.id.N",
"name": "$item.name.S"
}
#if($foreach.hasNext), #end
#end
]
requestTemplates:
application/json: !Sub |
{
"TableName": "${HeroesTable}",
"ScanFilter": {
"name": {
"AttributeValueList":[ {"S":"$input.params('name')"} ],
"ComparisonOperator": "CONTAINS"
}
}
}
passthroughBehavior: when_no_templates
httpMethod: POST
type: aws
The ‘aws’ service integation describes which API to invoke, eg. the DynamoDB ‘Scan’ API. The requestTemplate
creates an API request and uses a parameter from the request. The DynamoDB ‘Scan’ response will be converted by the
responseTemplate to a json response and uses Velocity Template Language syntax.
Conclusion
AWS Gateway Integrations makes it easy to integrate backends with an API specification. API Gateway can integrate with
AWS services (aws), http services (http, http_proxy), Lambda (aws_proxy), and can directly respond (mock).
aws-cfn-update allows us to separate all specifications in files and merge
them into a CloudFormation template when the stack is deployed. This allows for maintainable projects and reusable scripts.