Create a serverless RESTful API with API Gateway, CloudFormation, Lambda, and DynamoDB
This article teaches you how to create a serverless RESTful API on AWS. You will use CloudFormation to define the API Gateway in combination with Lambda to implement the functionality. DynamoDB is used to store the data. The example’s source code is available on GitHub and can be used to speed up your project.
If you are interested in defining the API in OpenAPI Specification or Swagger Specification read Create a serverless RESTful API with API Gateway, Swagger, Lambda, and DynamoDB instead!
If you are interested in deploying the API with the Serverless Framework read Create a serverless RESTful API with the Serverless Framework powered by API Gateway, Lambda, and DynamoDB instead!
Implementing a RESTful API with API Gateway, Lambda, and DynamoDB
API Gateway provides an HTTP API endpoint that is fully configurable. You define the HTTP resources (like /user
), the HTTP methods on that resources (like POST
, GET
, DELETE
, …) and the integration (e.g. Lambda function) that should be called to process the request. The Lambda function can then run whatever logic is needed to answer the request. API Gateway responds to the caller with the result of the Lambda function. The following figure demonstrates this flow.
If we zoom into the API Gateway component of the previous figure, we see what happens inside the API Gateway.
If you want to define a REST API you need to specify:
- Resources (e.g. GET /user)
- Methods on each resource (e.g. GET /user)
- Input
- Body Model
- Headers
- Path parameters (e.g. GET /user/:userId)
- Query parameters (e.g. GET /user?limit=10)
- Mapping HTTP input to integration input
- Integrations (e.g. Lambda functions)
- Mapping integration output to HTTP output
- Output
- Body Model
- Headers
You can use CloudFormation to define a REST API.
Defining a RESTful API with CloudFormation
CloudFormation uses the JavaScript Object Notation (JSON) to describe Resources like REST APIs. The JSON file is called a template and is the blueprint of your AWS infrastructure. A REST API in API Gateway composed of three components:
- Models: Define the input/output of the data
- Resources and Methods: e.g.
GET /user
to retrieve a list of all users - Endpoint: e.g.
https://api.somename.com/v1
You will now learn how to describe those components in CloudFormation. Remember that a CloudFormation template has the following structure:
{ |
Everything that you will learn now happens inside the Resources
block. The first resource is a REST API container to group all the following stuff.
"RestApi": { |
Describing Models
Models are defined with JSON Schema. The ToDo applications stores users with three required fields:
uid
: User idemail
phone
Mapped to a model in CloudFormation, this looks like that:
"UserModel": { |
You can also reference a model in a model for example if you want to define a list of users:
"UsersModel": { |
Now we need to define HTTP resources and methods.
Describing Resources and Methods
We want our API to expose the list of all users under GET /user
. In CloudFormation we need to define the HTTP resource /user
and the HTTP Method GET
. We also define two optional query parameters limit
and next
to provide a paging interface.
"UsersResource": { |
I left the Integration
block empty to show you this important aspect now in more detail. The Integration
block defines the Lambda function invoked when an HTTP request arrives.
"Integration": { |
Now it’s time to describe the endpoint that we need to use the REST API.
Describing the Endpoint
"RestApiDeployment": { |
It’s important that you explicitly depend on all the AWS::ApiGateway::Method
s.
Have a look at the following example to see the API in action.
Example
The example in this article reuses the multi-user ToDo application from chapter 10 in Amanzon Web Services in Action. You can find the code for the original example in the book’s code repository.
Setting up
clone the repository
git clone git@github.com:AWSinAction/apigateway.git |
create the lambda code file (lambda.zip
)
$ npm install --production |
create an S3 bucket in the US East (N. Virginia, us-east-1
) region and upload the lambda.zip
file (replace $S3Bucket
with a S3 bucket name)
export AWS_DEFAULT_REGION=us-east-1 |
create cloudformation stack
$ aws cloudformation create-stack --stack-name apigateway --template-body file://template_with_api.json --capabilities CAPABILITY_IAM --parameters ParameterKey=S3Bucket,ParameterValue=$S3Bucket |
wait until the stack is created (CREATE_COMPLETE
)
$ aws cloudformation wait stack-create-complete --stack-name apigateway |
get the $ApiId
$ aws cloudformation describe-stacks --stack-name apigateway --query Stacks[0].Outputs |
set the $ApiGatewayEndpoint
environment variable (replace $ApiId
)
export ApiGatewayEndpoint="$ApiId.execute-api.us-east-1.amazonaws.com/v1" |
Use the RESTful API
create a user
curl -vvv -X POST -d '{"email": "your@mail.com", "phone": "0123456789"}' -H "Content-Type: application/json" https://$ApiGatewayEndpoint/user |
list users
curl -vvv -X GET https://$ApiGatewayEndpoint/user |
create a task
curl -vvv -X POST -d '{"description": "test task"}' -H "Content-Type: application/json" https://$ApiGatewayEndpoint/user/$UserId/task |
list tasks
curl -vvv -X GET https://$ApiGatewayEndpoint/user/$UserId/task |
mark task as complete
curl -vvv -X PUT https://$ApiGatewayEndpoint/user/$UserId/task/$TaskId |
delete task
curl -vvv -X DELETE https://$ApiGatewayEndpoint/user/$UserId/task/$TaskId |
create a task with a category
curl -vvv -X POST -d '{"description": "test task", "category": "test"}' -H "Content-Type: application/json" https://$ApiGatewayEndpoint/user/$UserId/task |
list tasks by category
curl -vvv -X GET https://$ApiGatewayEndpoint/category/$Category/task |
Teardown
delete CloudFormation stack
$ aws cloudformation delete-stack --stack-name apigateway |
delete S3 bucket (replace $S3Bucket
)
$ aws s3 rb --force s3://$S3Bucket |
Summary
With API Gateway you can configure a RESTful API. You used a Lambda function to implement the functionality: Each HTTP request invokes a Lambda function. You have very limited overhead to operate your API because you only need to configure your API and implement the functionality. You don’t need to care about servers, scaling, and all the operational overhead.
To automate the configuration of API Gateway you used CloudFormation.
Further reading
- Article Serverless image resizing at any scale
- Article A look at DynamoDB
- Article 5 AWS mistakes you should avoid
- Article Building blocks for highly available systems
- Tag cloudformation
- Tag lambda
- Tag apigateway