Building an API Gateway with Lambda and DynamoDB for CRUD Operations

Building an API Gateway with Lambda and DynamoDB for CRUD Operations

Introduction

In the modern world of web and mobile applications, the need for efficient data storage and retrieval mechanisms is ever-growing. AWS (Amazon Web Services) provides developers with a powerful set of tools to accomplish this, including API Gateway, Lambda functions, and DynamoDB, a NoSQL database service. In this article, we will guide you through the process of creating an API Gateway, a Lambda function, and a DynamoDB table to enable CRUD operations (Create, Read, Update, Delete) on items stored in the DynamoDB table.

Understanding the Components

API Gateway: The API Gateway acts as a front door to your application, allowing clients to interact with your backend services through APIs. It provides a unified interface for multiple Lambda functions and serves as a communication layer between clients and your application's backend.

Lambda Function: AWS Lambda is a serverless compute service that allows you to run code without managing servers. It can be used to execute custom logic based on events, such as HTTP requests from the API Gateway. In our case, the Lambda function will handle the CRUD operations on the DynamoDB table.

DynamoDB: DynamoDB is a fully managed NoSQL database service offered by AWS. It provides high availability, scalability, and low-latency performance, making it an excellent choice for various applications, especially those requiring high read and write throughput.

Setting Up DynamoDB

First, we need to create a DynamoDB table to store the items. Head to the AWS Management Console, navigate to DynamoDB, and click on "Create table." Define the table name and primary key. For simplicity, let's use an attribute named "Id" as the primary key.

Creating the Lambda Function

Next, we will create the Lambda function that will handle CRUD operations on the DynamoDB table. To do this, follow these steps:

Open the AWS Lambda console and click "Create function."

Choose "Author from scratch" and provide a name, runtime ( here I use Node.js, but python can also be used), and execution role which we set here by clicking on change default execution role and ten Create a new role from AWS policy templates, giving the role a name and selecting "Simple microservice permissions" from policy templates

In the function code section, you can write the following code for your CRUD operations.

COPY

import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import {
  DynamoDBDocumentClient,
  ScanCommand,
  PutCommand,
  GetCommand,
  DeleteCommand,
} from "@aws-sdk/lib-dynamodb";

const client = new DynamoDBClient({});

const dynamo = DynamoDBDocumentClient.from(client);

const tableName = "crud-db1";

export const handler = async (event, context) => {
  let body;
  let statusCode = 200;
  const headers = {
    "Content-Type": "application/json",
  };

  try {
    switch (event.routeKey) {
      case "DELETE /items/{id}":
        await dynamo.send(
          new DeleteCommand({
            TableName: tableName,
            Key: {
              id: event.pathParameters.id,
            },
          })
        );
        body = `Deleted item ${event.pathParameters.id}`;
        break;
      case "GET /items/{id}":
        body = await dynamo.send(
          new GetCommand({
            TableName: tableName,
            Key: {
              id: event.pathParameters.id,
            },
          })
        );
        body = body.Item;
        break;
      case "GET /items":
        body = await dynamo.send(
          new ScanCommand({ TableName: tableName })
        );
        body = body.Items;
        break;
      case "PUT /items":
        let requestJSON = JSON.parse(event.body);
        await dynamo.send(
          new PutCommand({
            TableName: tableName,
            Item: {
                      id: requestJSON.id,
                      name: requestJSON.name,
                      email: requestJSON.email,
                      phoneNumber: requestJSON.phoneNumber

            },
          })
        );
        body = `Put item ${requestJSON.id}`;
        break;
      default:
        throw new Error(`Unsupported route: "${event.routeKey}"`);
    }
  } catch (err) {
    statusCode = 400;
    body = err.message;
  } finally {
    body = JSON.stringify(body);
  }

  return {
    statusCode,
    body,
    headers,
  };
};

Configuring the API Gateway for HTTP API

Now, let's proceed with setting up the API Gateway for our Lambda function using the HTTP API.

Go to the AWS API Gateway console and click on "Create API."

  1. Select "HTTP API" and provide a name for your API, describing its purpose or functionality.

    Select all defaults then create it.

Securing the API

Security is crucial for protecting your API and the data it handles. By default, HTTP APIs are publicly accessible, which may not be desired for sensitive applications. To add an extra layer of security, you can implement authentication and authorization mechanisms using AWS Cognito or API Gateway's custom authorizers. These are not covered in this article.

  1. AWS Cognito: AWS Cognito is a fully managed service that provides user sign-up, sign-in, and access control capabilities. You can use it to authenticate users before they access your API, ensuring only authorized users can interact with your resources. This is not covered in this article.

  2. API Gateway Custom Authorizers: Custom authorizers are Lambda functions that you can use to control access to your API. These functions can authenticate clients and authorize them based on specific criteria, such as API keys or request headers.

  3. By implementing one or both of these security measures, you can ensure that your API remains protected and accessible only to authenticated and authorized users.

Create routes

Routes are a way to send incoming API requests to backend resources. Routes consist of two parts: an HTTP method and a resource path, for example, GET /items. For this example API, we create four routes:

  • GET /items/{id}

  • GET /items

  • PUT /items

  • DELETE /items/{id}

To create routes
  1. Sign in to the API Gateway console at console.aws.amazon.com/apigateway.

  2. Choose your API.

  3. Choose Routes.

  4. Choose Create.

  5. For Method, choose GET.

  6. For the path, enter /items/{id}. The {id} at the end of the path is a path parameter that API Gateway retrieves from the request path when a client makes a request.

  7. Choose Create.

  8. Repeat steps 4-7 for GET /items, DELETE /items/{id}, and PUT /items.


Your API has routes for GET /items, GET /items/{id},DELETE
/items/{id}, and PUT /items.

Step 5: Create an integration

You create an integration to connect a route to backend resources. For this example API, you create one Lambda integration that you use for all routes.

To create an integration
  1. Sign in to the API Gateway console at console.aws.amazon.com/apigateway.

  2. Choose your API.

  3. Choose Integrations.

  4. Choose Manage integrations and then choose Create.

  5. Skip Attach this integration to a route. You complete that in a later step.

  6. For Integration type, choose Lambda function.

  7. For Lambda function, enter YourfunctionName.

  8. Choose Create.

Attach your integration to routes

For this example API, you use the same Lambda integration for all routes. After you attach the integration to all of the API's routes, your Lambda function is invoked when a client calls any of your routes.

To attach integrations to routes
  1. Sign in to the API Gateway console at console.aws.amazon.com/apigateway.

  2. Choose your API.

  3. Choose Integrations.

  4. Choose a route.

  5. Under Choose an existing integration, choose YourfunctionName.

  6. Choose Attach integration.

  7. Repeat steps 4-6 for all routes.

All routes show that an AWS Lambda integration is attached.


The console shows AWS Lambda on all routes to indicate that your integration is attached.

The Lambda function is triggered by incoming requests to the API Gateway and performs the appropriate CRUD operation on the DynamoDB table based on the contents of the request.

Using the API Gateway

After deploying the CloudFormation stack, you can use the ApiEndpoint output value to determine the URL of your API Gateway. You can then use this URL to send HTTP requests to your API Gateway and perform CRUD operations on your DynamoDB table.

Here are some examples of how you can use the different routes of your API Gateway:

  • Get all items: To retrieve all items from your DynamoDB table, you can send a GET request to the /items path of your API Gateway endpoint:

    COPY

        curl -X GET https://your-api-endpoint/items
    
  • Get a single item: To retrieve a single item from your DynamoDB table, you can send a GET request to the /items/{id} path of your API Gateway endpoint, replacing {id} with the ID of the item you want to retrieve:

    COPY

        curl -X GET https://your-api-endpoint/items/your-item-id
    
  • Create or update an item: To create or update an item in your DynamoDB table, you can send a PUT request to the /items path of your API Gateway endpoint with a JSON payload containing the item data:

    COPY

        curl -X PUT -H "Content-Type: application/json" -d '{"id": "your-item-id", "email": "your-email", "phoneNumber": "your-phone-number", "name": "your-name"}' https://your-api-endpoint/items
    
  • Delete an item: To delete an item from your DynamoDB table, you can send a DELETE request to the /items/{id} path of your API Gateway endpoint, replacing {id} with the ID of the item you want to delete:

    COPY

        curl -X DELETE https://your-api-endpoint/items/your-item-id
    

Or

Here I can use Postman instead of curl:

Using the API Gateway

After following the above steps, you can use the ApiEndpoint output value to determine the URL of your API Gateway. You can then use this URL to send HTTP requests to your API Gateway and perform CRUD operations on your DynamoDB table.

Here are some examples of how you can use the different routes of your API Gateway with Postman:

  • Get all items: To retrieve all items from your DynamoDB table, you can send a GET request to the /items path of your API Gateway endpoint. In Postman, create a new request and set the method to GET, then enter the URL of your API Gateway endpoint followed by /items in the address bar.

  • Get a single item: To retrieve a single item from your DynamoDB table, you can send a GET request to the /items/{id} path of your API Gateway endpoint, replacing {id} with the ID of the item you want to retrieve. In Postman, create a new request and set the method to GET, then enter the URL of your API Gateway endpoint followed by /items/your-item-id in the address bar.

  • Create or update an item: To create or update an item in your DynamoDB table, you can send a PUT request to the /items path of your API Gateway endpoint with a JSON payload containing the item data. In Postman, create a new request and set the method to PUT, then enter the URL of your API Gateway endpoint followed by /items in the address bar. In the "Body" tab, select "raw" and enter a JSON object containing the item data.

  • Delete an item: To delete an item from your DynamoDB table, you can send a DELETE request to the /items/{id} path of your API Gateway endpoint, replacing {id} with the ID of the item you want to delete. In Postman, create a new request and set the method to DELETE, then enter the URL of your API Gateway endpoint followed by /items/your-item-id in the address bar.

You can use these examples as a starting point to test your API Gateway and verify that it is correctly integrated with your Lambda function and DynamoDB table.

Using the Lambda Function

The Lambda function created by the CloudFormation template is triggered automatically by incoming requests to your API Gateway. You do not need to interact with it directly.

However, if you want to test or debug your Lambda function, you can use the AWS Lambda console or the AWS CLI to invoke it manually. You can create a test event that simulates an incoming request from your API Gateway and see how your function responds.

Using the DynamoDB Table

The DynamoDB table created by the CloudFormation template is used by your Lambda function to store and retrieve items. You do not need to interact with it directly.

However, if you want to view or modify the contents of your DynamoDB table, you can use the AWS Management Console or the AWS CLI. You can use these tools to perform operations such as scanning or querying your table, adding or updating items, or deleting items.

I hope this helps!