In this tutorial, you use Amazon API Gateway to create a REST API and a resource (DynamoDBManager
). You define one method (POST
) on the resource, and create a Lambda function (LambdaFunctionOverHttps
) that backs the POST
method. That way, when you call the API through an HTTPS endpoint, API Gateway invokes the Lambda function.
The POST
method that you define on the DynamoDBManager
resource supports the following Amazon DynamoDB operations:
- Create, update, and delete an item.
- Read an item.
- Scan an item.
- Other operations (echo, ping), not related to DynamoDB, that you can use for testing.
Using API Gateway with Lambda also provides advanced capabilities, such as:
- Full request passthrough – Using the Lambda proxy (
AWS_PROXY
) integration type, a Lambda function can receive an entire HTTP request (instead of just the request body) and set the HTTP response (instead of just the response body). - Catch-all methods – Using the
ANY
catch-all method, you can map all methods of an API resource to a single Lambda function with a single mapping. - Catch-all resources – Using a greedy path variable (
{proxy+}
), you can map all sub-paths of a resource to a Lambda function without any additional configuration.
For more information about these API Gateway features, see Set up a proxy integration with a proxy resource in the API Gateway Developer Guide.
Topics
- Prerequisites
- Create an execution role
- Create the function
- Test the function
- Create a REST API using API Gateway
- Create a DynamoDB table
- Test the setup
- Clean up your resources
This tutorial assumes that you have some knowledge of basic Lambda operations and the Lambda console. If you haven't already, follow the instructions in Getting started with Lambda to create your first Lambda function.
To complete the following steps, you need a command line terminal or shell to run commands. Commands and the expected output are listed in separate blocks:
aws --version
You should see the following output:
aws-cli/2.0.57 Python/3.7.4 Darwin/19.6.0 exe/x86_64
For long commands, an escape character (\
) is used to split a command over multiple lines.
On Linux and macOS, use your preferred shell and package manager. On Windows 10, you can install the Windows Subsystem for Linux to get a Windows-integrated version of Ubuntu and Bash.
Create an execution role. This AWS Identity and Access Management (IAM) role uses a custom policy to give your Lambda function permission to access the required AWS resources. Note that you must first create the policy and then create the execution role.
To create a custom policy
-
Open the Policies page of the IAM console.
-
Choose Create Policy.
-
Choose the JSON tab, and then paste the following custom policy into the JSON editor.
{ "Version": "2012-10-17", "Statement": [ { "Sid": "Stmt1428341300017", "Action": [ "dynamodb:DeleteItem", "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:Query", "dynamodb:Scan", "dynamodb:UpdateItem" ], "Effect": "Allow", "Resource": "*" }, { "Sid": "", "Resource": "*", "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Effect": "Allow" } ] }
This policy includes permissions for your function to access DynamoDB and Amazon CloudWatch Logs.
-
Choose Next: Tags.
-
Choose Next: Review.
-
Under Review policy, for the policy Name, enter lambda-apigateway-policy.
-
Choose Create policy.
To create an execution role
-
Open the Roles page of the IAM console.
-
Choose Create role.
-
For the type of trusted entity, choose AWS service.
-
For the use case, choose Lambda.
-
Choose Next: Permissions.
-
In the policy search box, enter lambda-apigateway-policy.
-
In the search results, select the policy that you created (
lambda-apigateway-policy
), and then choose Next: Tags. -
Choose Next: Review.
-
Under Review, for the Role name, enter lambda-apigateway-role.
-
Choose Create role.
-
On the Roles page, choose the name of your role (
lambda-apigateway-role
). -
On the Summary page, copy the Role ARN. You need this later in the tutorial.
The following code example receives an API Gateway event input and processes the messages that this input contains. For illustration, the code writes some of the incoming event data to CloudWatch Logs.
Example index.js
console.log('Loading function');
var AWS = require('aws-sdk');
var dynamo = new AWS.DynamoDB.DocumentClient();
/**
* Provide an event that contains the following keys:
*
* - operation: one of the operations in the switch statement below
* - tableName: required for operations that interact with DynamoDB
* - payload: a parameter to pass to the operation being performed
*/
exports.handler = function(event, context, callback) {
//console.log('Received event:', JSON.stringify(event, null, 2));
var operation = event.operation;
if (event.tableName) {
event.payload.TableName = event.tableName;
}
switch (operation) {
case 'create':
dynamo.put(event.payload, callback);
break;
case 'read':
dynamo.get(event.payload, callback);
break;
case 'update':
dynamo.update(event.payload, callback);
break;
case 'delete':
dynamo.delete(event.payload, callback);
break;
case 'list':
dynamo.scan(event.payload, callback);
break;
case 'echo':
callback(null, "Success");
break;
case 'ping':
callback(null, "pong");
break;
default:
callback(`Unknown operation: ${operation}`);
}
};
To create the function
-
Save the code example as a file named
index.js
. -
Create a deployment package.
zip function.zip index.js
-
Create a Lambda function using the
create-function
AWS Command Line Interface (AWS CLI) command. For therole
parameter, enter the execution role's Amazon Resource Name (ARN), which you copied earlier.aws lambda create-function --function-name LambdaFunctionOverHttps \ --zip-file fileb://function.zip --handler index.handler --runtime nodejs12.x \ --role arn:aws:iam::123456789012:role/service-role/lambda-apigateway-role
Example LambdaFunctionOverHttps.py
from __future__ import print_function
import boto3
import json
print('Loading function')
def handler(event, context):
'''Provide an event that contains the following keys:
- operation: one of the operations in the operations dict below
- tableName: required for operations that interact with DynamoDB
- payload: a parameter to pass to the operation being performed
'''
#print("Received event: " + json.dumps(event, indent=2))
operation = event['operation']
if 'tableName' in event:
dynamo = boto3.resource('dynamodb').Table(event['tableName'])
operations = {
'create': lambda x: dynamo.put_item(**x),
'read': lambda x: dynamo.get_item(**x),
'update': lambda x: dynamo.update_item(**x),
'delete': lambda x: dynamo.delete_item(**x),
'list': lambda x: dynamo.scan(**x),
'echo': lambda x: x,
'ping': lambda x: 'pong'
}
if operation in operations:
return operations[operation](event.get('payload'))
else:
raise ValueError('Unrecognized operation "{}"'.format(operation))
To create the function
-
Save the code example as a file named
LambdaFunctionOverHttps.py
. -
Create a deployment package.
zip function.zip LambdaFunctionOverHttps.py
-
Create a Lambda function using the
create-function
AWS Command Line Interface (AWS CLI) command. For therole
parameter, enter the execution role's Amazon Resource Name (ARN), which you copied earlier.aws lambda create-function --function-name LambdaFunctionOverHttps \ --zip-file fileb://function.zip --handler LambdaFunctionOverHttps.handler --runtime python3.8 \ --role arn:aws:iam::123456789012:role/service-role/lambda-apigateway-role
Example LambdaFunctionOverHttps.go
package main
import (
"context"
"fmt"
"github.com/aws/aws-lambda-go/events"
runtime "github.com/aws/aws-lambda-go/lambda"
)
func main() {
runtime.Start(handleRequest)
}
func handleRequest(ctx context.Context, request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
fmt.Printf("Processing request data for request %s.\n", request.RequestContext.RequestID)
fmt.Printf("Body size = %d.\n", len(request.Body))
fmt.Println("Headers:")
for key, value := range request.Headers {
fmt.Printf(" %s: %s\n", key, value)
}
return events.APIGatewayProxyResponse{Body: request.Body, StatusCode: 200}, nil
}
To create the function
-
Save the code example as a file named
LambdaFunctionOverHttps.go
. -
Compile your executable.
GOOS=linux go build LambdaFunctionOverHttps.go
-
Create a deployment package.
zip function.zip LambdaFunctionOverHttps
-
Create a Lambda function using the
create-function
AWS Command Line Interface (AWS CLI) command. For therole
parameter, enter the execution role's Amazon Resource Name (ARN), which you copied earlier.aws lambda create-function --function-name LambdaFunctionOverHttps \ --zip-file fileb://function.zip --handler LambdaFunctionOverHttps --runtime go1.x \ --role arn:aws:iam::123456789012:role/service-role/lambda-apigateway-role
Test the Lambda function manually using the following sample event data. You can invoke the function using the invoke
AWS CLI command or by using the Lambda console.
To test the Lambda function (AWS CLI)
-
Save the following JSON as a file named
input.txt
.{ "operation": "echo", "payload": { "somekey1": "somevalue1", "somekey2": "somevalue2" } }
-
Run the following
invoke
AWS CLI command:aws lambda invoke --function-name LambdaFunctionOverHttps \ --payload file://input.txt outputfile.txt
The cli-binary-format option is required if you are using AWS CLI version 2. You can also configure this option in your AWS CLI config file.
-
Verify the output in the file
outputfile.txt
.
In this section, you create an API Gateway REST API (DynamoDBOperations
) with one resource (DynamoDBManager
) and one method (POST
). You associate the POST
method with your Lambda function. Then, you test the setup.
When your API method receives an HTTP request, API Gateway invokes your Lambda function.
In the following steps, you create the DynamoDBOperations
REST API using the API Gateway console.
To create the API
-
Open the API Gateway console.
-
Choose Create API.
-
In the REST API box, choose Build.
-
Under Create new API, choose New API.
-
Under Settings, do the following:
-
For API name, enter DynamoDBOperations.
-
For Endpoint Type, choose Regional.
-
-
Choose Create API.
In the following steps, you create a resource named DynamoDBManager
in your REST API.
To create the resource
-
In the API Gateway console, in the Resources tree of your API, make sure that the root (
/
) level is highlighted. Then, choose Actions, Create Resource. -
Under New child resource, do the following:
-
For Resource Name, enter DynamoDBManager.
-
Keep Resource Path set to
/dynamodbmanager
.
-
-
Choose Create Resource.
In the following steps, you create a POST
method on the DynamoDBManager
resource that you created in the previous section.
To create the method
-
In the API Gateway console, in the Resources tree of your API, make sure that
/dynamodbmanager
is highlighted. Then, choose Actions, Create Method. -
In the small dropdown menu that appears under
/dynamodbmanager
, choosePOST
, and then choose the check mark icon. -
In the method's Setup pane, do the following:
-
For Integration type, choose Lambda Function.
-
For Lambda Region, choose the same AWS Region as your Lambda function.
-
For Lambda Function, enter the name of your function (LambdaFunctionOverHttps).
-
Select Use Default Timeout.
-
Choose Save.
-
-
In the Add Permission to Lambda Function dialog box, choose OK.
Create the DynamoDB table that your Lambda function uses.
To create the DynamoDB table
-
Open the Tables page of the DynamoDB console.
-
Choose Create table.
-
Under Table details, do the following:
-
For Table name, enter lambda-apigateway.
-
For Partition key, enter id, and keep the data type set as String.
-
-
Under Settings, keep the Default settings.
-
Choose Create table.
You're now ready to test the setup. You can send requests to your POST
method directly from the API Gateway console. In this step, you use a create
operation followed by an update
operation.
To create an item in your DynamoDB table
Your Lambda function can use the create
operation to create an item in your DynamoDB table.
-
In the API Gateway console, choose the name of your REST API (
DynamoDBOperations
). -
In the Resources tree, under
/dynamodbmanager
, choose yourPOST
method. -
In the Method Execution pane, in the Client box, choose Test.
-
In the Method Test pane, keep Query Strings and Headers empty. For Request Body, paste the following JSON:
{ "operation": "create", "tableName": "lambda-apigateway", "payload": { "Item": { "id": "1234ABCD", "number": 5 } } }
-
Choose Test.
The test results should show status 200
, indicating that the create
operation was successful. To confirm, you can check that your DynamoDB table now contains an item with "id": "1234ABCD"
and "number": "5"
.
To update the item in your DynamoDB table
You can also update items in the table using the update
operation.
-
In the API Gateway console, return to your POST method's Method Test pane.
-
In the Method Test pane, keep Query Strings and Headers empty. In Request Body, paste the following JSON:
{ "operation": "update", "tableName": "lambda-apigateway", "payload": { "Key": { "id": "1234ABCD" }, "AttributeUpdates": { "number": { "Value": 10 } } } }
-
Choose Test.
The test results should show status 200
, indicating that the update
operation was successful. To confirm, you can check that your DynamoDB table now contains an updated item with "id": "1234ABCD"
and "number": "10"
.
You can now delete the resources that you created for this tutorial, unless you want to retain them. By deleting AWS resources that you're no longer using, you prevent unnecessary charges to your AWS account.
To delete the Lambda function
-
Open the Functions page of the Lambda console.
-
Select the function that you created.
-
Choose Actions, then choose Delete.
-
Choose Delete.
To delete the execution role
-
Open the Roles page of the IAM console.
-
Select the execution role that you created.
-
Choose Delete role.
-
Choose Yes, delete.
To delete the API
-
Open the APIs page of the API Gateway console.
-
Select the API you created.
-
Choose Actions, Delete.
-
Choose Delete.
To delete the DynamoDB table
-
Open the Tables page of the DynamoDB console.
-
Select the table you created.
-
Choose Delete.
-
Enter delete in the text box.
-
Choose Delete.