Tutorial: Using Lambda with API Gateway - AWS Lambda

Tutorial: Using Lambda with API Gateway

In this tutorial, you create a REST API through which you invoke a Lambda function using an HTTP request. Your Lambda function will perform create, read, update, and delete (CRUD) operations on a DynamoDB table. This function is provided here for demonstration, but you will learn to configure an API Gateway REST API that can invoke any Lambda function.

Services and resources used in this tutorial

Using API Gateway provides users with a secure HTTP endpoint to invoke your Lambda function and can help manage large volumes of calls to your function by throttling traffic and automatically validating and authorizing API calls. API Gateway also provides flexible security controls using AWS Identity and Access Management (IAM) and Amazon Cognito. This is useful for use cases where advance authorization is required for calls to your application.

To complete this tutorial, you will go through the following stages:

  1. Create and configure a Lambda function in Python or Node.js to perform operations on a DynamoDB table.

  2. Create a REST API in API Gateway to connect to your Lambda function.

  3. Create a DynamoDB table and test it with your Lambda function in the console.

  4. Deploy your API and test the full setup using curl in a terminal.

By completing these stages, you will learn how to use API Gateway to create an HTTP endpoint that can securely invoke a Lambda function at any scale. You will also learn how to deploy your API, and how to test it in the console and by sending an HTTP request using a terminal.

Prerequisites

If you do not have an AWS account, complete the following steps to create one.

To sign up for an AWS account
  1. Open https://portal.aws.amazon.com/billing/signup.

  2. Follow the online instructions.

    Part of the sign-up procedure involves receiving a phone call and entering a verification code on the phone keypad.

    When you sign up for an AWS account, an AWS account root user is created. The root user has access to all AWS services and resources in the account. As a security best practice, assign administrative access to a user, and use only the root user to perform tasks that require root user access.

AWS sends you a confirmation email after the sign-up process is complete. At any time, you can view your current account activity and manage your account by going to https://aws.amazon.com/ and choosing My Account.

After you sign up for an AWS account, secure your AWS account root user, enable AWS IAM Identity Center, and create an administrative user so that you don't use the root user for everyday tasks.

Secure your AWS account root user
  1. Sign in to the AWS Management Console as the account owner by choosing Root user and entering your AWS account email address. On the next page, enter your password.

    For help signing in by using root user, see Signing in as the root user in the AWS Sign-In User Guide.

  2. Turn on multi-factor authentication (MFA) for your root user.

    For instructions, see Enable a virtual MFA device for your AWS account root user (console) in the IAM User Guide.

Create a user with administrative access
  1. Enable IAM Identity Center.

    For instructions, see Enabling AWS IAM Identity Center in the AWS IAM Identity Center User Guide.

  2. In IAM Identity Center, grant administrative access to a user.

    For a tutorial about using the IAM Identity Center directory as your identity source, see Configure user access with the default IAM Identity Center directory in the AWS IAM Identity Center User Guide.

Sign in as the user with administrative access
  • To sign in with your IAM Identity Center user, use the sign-in URL that was sent to your email address when you created the IAM Identity Center user.

    For help signing in using an IAM Identity Center user, see Signing in to the AWS access portal in the AWS Sign-In User Guide.

Assign access to additional users
  1. In IAM Identity Center, create a permission set that follows the best practice of applying least-privilege permissions.

    For instructions, see Create a permission set in the AWS IAM Identity Center User Guide.

  2. Assign users to a group, and then assign single sign-on access to the group.

    For instructions, see Add groups in the AWS IAM Identity Center User Guide.

If you have not yet installed the AWS Command Line Interface, follow the steps at Installing or updating the latest version of the AWS CLI to install it.

The tutorial requires a command line terminal or shell to run commands. In Linux and macOS, use your preferred shell and package manager.

Note

In Windows, some Bash CLI commands that you commonly use with Lambda (such as zip) are not supported by the operating system's built-in terminals. To get a Windows-integrated version of Ubuntu and Bash, install the Windows Subsystem for Linux.

Create a permissions policy

Step 1 create a permissions policy

Before you can create an execution role for your Lambda function, you first need to create a permissions policy to give your function permission to access the required AWS resources. For this tutorial, the policy allows Lambda to perform CRUD operations on a DynamoDB table and write to Amazon CloudWatch Logs.

To create the policy
  1. Open the Policies page of the IAM console.

  2. Choose Create Policy.

  3. 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" } ] }
  4. Choose Next: Tags.

  5. Choose Next: Review.

  6. Under Review policy, for the policy Name, enter lambda-apigateway-policy.

  7. Choose Create policy.

Create an execution role

Step 2 create an execution role

An execution role is an AWS Identity and Access Management (IAM) role that grants a Lambda function permission to access AWS services and resources. To enable your function to perform operations on a DynamoDB table, you attach the permissions policy you created in the previous step.

To create an execution role and attach your custom permissions policy
  1. Open the Roles page of the IAM console.

  2. Choose Create role.

  3. For the type of trusted entity, choose AWS service, then for the use case, choose Lambda.

  4. Choose Next.

  5. In the policy search box, enter lambda-apigateway-policy.

  6. In the search results, select the policy that you created (lambda-apigateway-policy), and then choose Next.

  7. Under Role details, for the Role name, enter lambda-apigateway-role, then choose Create role.

Later in the tutorial, you need the Amazon Resource Name (ARN) of the role you just created. On the Roles page of the IAM console, choose the name of your role (lambda-apigateway-role) and copy the Role ARN displayed on the Summary page.

Create the function

Step 3 create the function

The following code example receives an event input from API Gateway specifying an operation to perform on the DynamoDB table you will create and some payload data. If the parameters the function receives are valid, it performs the requested operation on the table.

Node.js
Example index.mjs

Note the region setting. This must match the AWS Region where you deploy the function and create the DynamoDB table.

import { DynamoDBDocumentClient, PutCommand, GetCommand, UpdateCommand, DeleteCommand} from "@aws-sdk/lib-dynamodb"; import { DynamoDBClient } from "@aws-sdk/client-dynamodb"; const ddbClient = new DynamoDBClient({ region: "us-east-2" }); const ddbDocClient = DynamoDBDocumentClient.from(ddbClient); // Define the name of the DDB table to perform the CRUD operations on const tablename = "lambda-apigateway"; /** * Provide an event that contains the following keys: * * - operation: one of 'create,' 'read,' 'update,' 'delete,' or 'echo' * - payload: a JSON object containing the parameters for the table item * to perform the operation on */ export const handler = async (event, context) => { const operation = event.operation; if (operation == 'echo'){ return(event.payload); } else { event.payload.TableName = tablename; let response; switch (operation) { case 'create': response = await ddbDocClient.send(new PutCommand(event.payload)); break; case 'read': response = await ddbDocClient.send(new GetCommand(event.payload)); break; case 'update': response = ddbDocClient.send(new UpdateCommand(event.payload)); break; case 'delete': response = ddbDocClient.send(new DeleteCommand(event.payload)); break; default: response = 'Unknown operation: ${operation}'; } console.log(response); return response; } };
Note

In this example, the name of the DynamoDB table is defined as a variable in your function code. In a real application, best practice is to pass this parameter as an environment variable and to avoid hardcoding the table name. For more information see Using AWS Lambda environment variables.

To create the function
  1. Save the code example as a file named index.mjs and, if necessary, edit the AWS region specified in the code. The region specified in the code must be the same as the region in which you create your DynamoDB table later in the tutorial.

  2. Create a deployment package using the following zip command.

    zip function.zip index.mjs
  3. Create a Lambda function using the create-function AWS CLI command. For the role parameter, enter the execution role's Amazon Resource Name (ARN) that you copied earlier.

    aws lambda create-function \ --function-name LambdaFunctionOverHttps \ --zip-file fileb://function.zip \ --handler index.handler \ --runtime nodejs20.x \ --role arn:aws:iam::123456789012:role/service-role/lambda-apigateway-role
Python 3
Example LambdaFunctionOverHttps.py
import boto3 # Define the DynamoDB table that Lambda will connect to table_name = "lambda-apigateway" # Create the DynamoDB resource dynamo = boto3.resource('dynamodb').Table(table_name) # Define some functions to perform the CRUD operations def create(payload): return dynamo.put_item(Item=payload['Item']) def read(payload): return dynamo.get_item(Key=payload['Key']) def update(payload): return dynamo.update_item(**{k: payload[k] for k in ['Key', 'UpdateExpression', 'ExpressionAttributeNames', 'ExpressionAttributeValues'] if k in payload}) def delete(payload): return dynamo.delete_item(Key=payload['Key']) def echo(payload): return payload operations = { 'create': create, 'read': read, 'update': update, 'delete': delete, 'echo': echo, } def lambda_handler(event, context): '''Provide an event that contains the following keys: - operation: one of the operations in the operations dict below - payload: a JSON object containing parameters to pass to the operation being performed ''' operation = event['operation'] payload = event['payload'] if operation in operations: return operations[operation](payload) else: raise ValueError(f'Unrecognized operation "{operation}"')
Note

In this example, the name of the DynamoDB table is defined as a variable in your function code. In a real application, best practice is to pass this parameter as an environment variable and to avoid hardcoding the table name. For more information see Using AWS Lambda environment variables.

To create the function
  1. Save the code example as a file named LambdaFunctionOverHttps.py.

  2. Create a deployment package using the following zip command.

    zip function.zip LambdaFunctionOverHttps.py
  3. Create a Lambda function using the create-function AWS CLI command. For the role parameter, enter the execution role's Amazon Resource Name (ARN) that you copied earlier.

    aws lambda create-function \ --function-name LambdaFunctionOverHttps \ --zip-file fileb://function.zip \ --handler LambdaFunctionOverHttps.lambda_handler \ --runtime python3.12 \ --role arn:aws:iam::123456789012:role/service-role/lambda-apigateway-role

Invoke the function using the AWS CLI

Step 4 invoke the function using the AWS CLI

Before integrating your function with API Gateway, confirm that you have deployed the function successfully. Create a test event containing the parameters your API Gateway API will send to Lambda and use the AWS CLI invoke command to run your function.

To invoke the Lambda function with the AWS CLI
  1. Save the following JSON as a file named input.txt.

    { "operation": "echo", "payload": { "somekey1": "somevalue1", "somekey2": "somevalue2" } }
  2. Run the following invoke AWS CLI command.

    aws lambda invoke \ --function-name LambdaFunctionOverHttps \ --payload file://input.txt outputfile.txt \ --cli-binary-format raw-in-base64-out

    The cli-binary-format option is required if you're using AWS CLI version 2. To make this the default setting, run aws configure set cli-binary-format raw-in-base64-out. For more information, see AWS CLI supported global command line options in the AWS Command Line Interface User Guide for Version 2.

    You should see the following response:

    { "StatusCode": 200, "ExecutedVersion": "LATEST" }
  3. Confirm that your function performed the echo operation you specified in the JSON test event. Inspect the outputfile.txt file and verify it contains the following:

    {"somekey1": "somevalue1", "somekey2": "somevalue2"}

Create a REST API using API Gateway

Step 5 create the API

In this step, you create the API Gateway REST API you will use to invoke your Lambda function.

To create the API
  1. Open the API Gateway console.

  2. Choose Create API.

  3. In the REST API box, choose Build.

  4. Under API details, leave New API selected, and for API Name, enter DynamoDBOperations.

  5. Choose Create API.

Create a resource on your REST API

Step 6 create the API resource

To add an HTTP method to your API, you first need to create a resource for that method to operate on. Here you create the resource to manage your DynamoDB table.

To create the resource
  1. In the API Gateway console, on the Resources page for your API, choose Create Resource.

  2. In Resource details, for Resource name enter DynamoDBManager.

  3. Choose Create Resource.

Create an HTTP POST method

Step 7 create the HTTP POST method

In this step, you create a method (POST) for your DynamoDBManager resource. You link this POST method to your Lambda function so that when the method receives an HTTP request, API Gateway invokes your Lambda function.

Note

For the purpose of this tutorial, one HTTP method (POST) is used to invoke a single Lambda function which carries out all of the operations on your DynamoDB table. In a real application, best practice is to use a different Lambda function and HTTP method for each operation. For more information, see The Lambda monolith in Serverless Land.

To create the POST method
  1. On the Resources page for your API, ensure that the /DynamoDBManager resource is highlighted. Then, in the Methods pane, choose Create Method.

  2. For Method type, choose POST.

  3. For Integration type, leave Lambda function selected.

  4. For Lambda function, choose the Amazon Resource Name (ARN) for your function (LambdaFunctionOverHttps).

  5. Choose Create method.

Create a DynamoDB table

Step 8 create a DynamoDB table

Create an empty DynamoDB table that your Lambda function will perform CRUD operations on.

To create the DynamoDB table
  1. Open the Tables page of the DynamoDB console.

  2. Choose Create table.

  3. Under Table details, do the following:

    1. For Table name, enter lambda-apigateway.

    2. For Partition key, enter id, and keep the data type set as String.

  4. Under Table settings, keep the Default settings.

  5. Choose Create table.

Test the integration of API Gateway, Lambda, and DynamoDB

Step 9 test the integration of API Gateway, Lambda, and DynamoDB

You're now ready to test the integration of your API Gateway API method with your Lambda function and your DynamoDB table. Using the API Gateway console, you send requests directly to your POST method using the console's test function. In this step, you first use a create operation to add a new item to your DynamoDB table, then you use an update operation to modify the item.

Test 1: To create a new item in your DynamoDB table
  1. In the API Gateway console, choose your API (DynamoDBOperations).

  2. Choose the POST method under the DynamoDBManager resource.

    Choose the POST method under the DynamoDBManager resource.
  3. Choose the Test tab. You might need to choose the right arrow button to show the tab.

  4. Under Test method, leave Query strings and Headers empty. For Request body, paste the following JSON:

    { "operation": "create", "payload": { "Item": { "id": "1234ABCD", "number": 5 } } }
  5. Choose Test.

    The results that are displayed when the test completes should show status 200. This status code indicates that the create operation was successful.

    To confirm, check that your DynamoDB table now contains the new item.

  6. Open the Tables page of the DynamoDB console and choose the lambda-apigateway table.

  7. Chose Explore table items. In the Items returned pane, you should see one item with the id 1234ABCD and the number 5.

Test 2: To update the item in your DynamoDB table
  1. In the API Gateway console, return to your POST method's Test tab.

  2. Under Test method, leave Query strings and Headers empty. For Request body, paste the following JSON:

    { "operation": "update", "payload": { "Key": { "id": "1234ABCD" }, "UpdateExpression": "SET #num = :newNum", "ExpressionAttributeNames": { "#num": "number" }, "ExpressionAttributeValues": { ":newNum": 10 } } }
  3. Choose Test.

    The results which are displayed when the test completes should show status 200. This status code indicates that the update operation was successful.

    To confirm, check that the item in yout DynamoDB table has been modified.

  4. Open the Tables page of the DynamoDB console and choose the lambda-apigateway table.

  5. Chose Explore table items. In the Items returned pane, you should see one item with the id 1234ABCD and the number 10.

Deploy the API

Step 10 deploy the API

For a client to call the API, you must create a deployment and an associated stage. A stage represents a snapshot of your API including its methods and integrations.

To deploy the API
  1. Open the APIs page of the API Gateway console and choose the DynamoDBOperations API.

  2. On the Resources page for your API choose Deploy API.

  3. For Stage, choose *New stage*, then for Stage name, enter test.

  4. Choose Deploy.

  5. In the Stage details pane, copy the Invoke URL. You will use this in the next step to invoke your function using an HTTP request.

Use curl to invoke your function using HTTP requests

Step 11 invoke the function with an HTTP request

You can now invoke your Lambda function by issuing an HTTP request to your API. In this step, you will create a new item in your DynamoDB table and then perform read, update, and delete operations on that item.

To create an item in your DynamoDB table using curl
  1. Run the following curl command using the invoke URL you copied in the previous step. When you use curl with the -d (data) option, it automatically uses the HTTP POST method.

    curl https://l8togsqxd8.execute-api.us-east-2.amazonaws.com/test/DynamoDBManager \ -d '{"operation": "create", "payload": {"Item": {"id": "5678EFGH", "number": 15}}}'

    If the operation was successful, you should see a response returned with an HTTP status code of 200.

  2. You can also use the DynamoDB console to verify that the new item is in your table by doing the following:

    1. Open the Tables page of the DynamoDB console and choose the lambda-apigateway table.

    2. Choose Explore table items. In the Items returned pane, you should see an item with the id 5678EFGH and the number 15.

To read the item in your DynamoDB table using curl
  • Run the following curl command to read the value of the item you just created. Use your own invoke URL.

    curl https://avos4dr2rk.execute-api.us-east-2.amazonaws.com/test/DynamoDBManager -d \ '{"operation": "read", "payload": {"Key": {"id": "5678EFGH"}}}'

    You should see output like one of the following depending on whether you chose the Node.js or Python function code:

    Node.js
    {"$metadata":{"httpStatusCode":200,"requestId":"7BP3G5Q0C0O1E50FBQI9NS099JVV4KQNSO5AEMVJF66Q9ASUAAJG", "attempts":1,"totalRetryDelay":0},"Item":{"id":"5678EFGH","number":15}}
    Python
    {"Item":{"id":"5678EFGH","number":15},"ResponseMetadata":{"RequestId":"QNDJICE52E86B82VETR6RKBE5BVV4KQNSO5AEMVJF66Q9ASUAAJG", "HTTPStatusCode":200,"HTTPHeaders":{"server":"Server","date":"Wed, 31 Jul 2024 00:37:01 GMT","content-type":"application/x-amz-json-1.0", "content-length":"52","connection":"keep-alive","x-amzn-requestid":"QNDJICE52E86B82VETR6RKBE5BVV4KQNSO5AEMVJF66Q9ASUAAJG","x-amz-crc32":"2589610852"}, "RetryAttempts":0}}
To update the item in your DynamoDB table using curl
  1. Run the following curl command to update the item you just created by changing the number value. Use your own invoke URL.

    curl https://avos4dr2rk.execute-api.us-east-2.amazonaws.com/test/DynamoDBManager \ -d '{"operation": "update", "payload": {"Key": {"id": "5678EFGH"}, "UpdateExpression": "SET #num = :new_value", "ExpressionAttributeNames": {"#num": "number"}, "ExpressionAttributeValues": {":new_value": 42}}}'
  2. To confirm that the value of number for the item has been updated, run another read command:

    curl https://avos4dr2rk.execute-api.us-east-2.amazonaws.com/test/DynamoDBManager \ -d '{"operation": "read", "payload": {"Key": {"id": "5678EFGH"}}}'
To delete the item in your DynamoDB table using curl
  1. Run the following curl command to delete the item you just created. Use your own invoke URL.

    curl https://l8togsqxd8.execute-api.us-east-2.amazonaws.com/test/DynamoDBManager \ -d '{"operation": "delete", "payload": {"Key": {"id": "5678EFGH"}}}'
  2. Confirm that the delete operation was successful. In the Items returned pane of the DynamoDB console Explore items page, verify that the item with id 5678EFGH is no longer in the table.

Clean up your resources (optional)

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
  1. Open the Functions page of the Lambda console.

  2. Select the function that you created.

  3. Choose Actions, Delete.

  4. Type delete in the text input field and choose Delete.

To delete the execution role
  1. Open the Roles page of the IAM console.

  2. Select the execution role that you created.

  3. Choose Delete.

  4. Enter the name of the role in the text input field and choose Delete.

To delete the API
  1. Open the APIs page of the API Gateway console.

  2. Select the API you created.

  3. Choose Actions, Delete.

  4. Choose Delete.

To delete the DynamoDB table
  1. Open the Tables page of the DynamoDB console.

  2. Select the table you created.

  3. Choose Delete.

  4. Enter delete in the text box.

  5. Choose Delete table.