@jialin.huang
FRONT-ENDBACK-ENDNETWORK, HTTPOS, COMPUTERCLOUD, AWS, Docker
To live is to risk it all Otherwise you are just an inert chunk of randomly assembled molecules drifting wherever the Universe blows you

© 2024 jialin00.com

Original content since 2022

back
RSS

Serverless: Lambda, API Gateway, DynamoDB Together

https://aws.amazon.com/tw/serverless/

All services mentioned are belonging to serverless

WHY

you don't need to launch an entire backend project. You can simply upload a single file (like an index.js) to get your function running. This dramatically simplifies the deployment process and reduces the complexity of managing dirty server infrastructure.

Instead of spending time on server configuration and management tasks, we Developers can focus on coding that directly related to our main goal.

Here's what we're going to do

  1. When a user sends a request through our API Gateway, it's like ringing a bell.
  1. This "bell" wakes up Lambda to handle the task.
  1. It might be checking on a user's order status or saving a new review to our DynamoDB database.
  1. Once Lambda's done its job, it return the results and sends them back to the client through the API Gateway.

Step 1: Create a DynamoDB table for Later Usage

Just go create a table

Nothing to care.

Step 2: Create a Lambda Function

  1. Lambda > Create function.
  1. Pick your flavor - from scratch or use a blueprint.
    1. if you choose from scratch, then upload your code.
  1. Name it and choose your language.
  1. Set up permissions.
    1. need do make new role attach some DynamoDB policies later
      1. like AmazonDynamoDBFullAccess

        (I am so lazy, i chose full access. NOT RECOMMENDED)

        Better mindset is least privilege access, target spec resource arn instead. (go Step 4)

  1. Done!

Step 3: API Gateway Setup

  1. API Gateway > Create API and choose REST API type.
  1. Give a name and it’s just a name. Do not let it bother you.
  1. Create your resources (URL paths).
    1. Create methods (GET, POST, etc.).
    1. Attach your Lambda function.

      click Lambda proxy integration(Send the request to your Lambda function as a structured event.) or it will get undefined method in lambda context.

      or if already created but still get undefined method, go resources > endpoint > method, there’s a Integration request tab > Edit, turn on Lambda proxy integration

  1. Set up your responses.

.. repeat above if you need multiple endpoints or methods

  1. then last thing Deploy API to a stage (dev, prod).

    stage it’s like a little versioning and target environment

    you can have dev stage, production stage, v1, etc

  1. To get the API endpoint, go Stage > Choose Stage to get Invoke URL for your client usage.
  1. now connection between Lambda and API Gateway done.

Step 4: Lambda can access DynamoDB now!

  1. Lambda function > Configuration tab
  1. Permissions section and find the Role name.
  1. Click on that role name. This'll take you straight to IAM.
  1. Now, in IAM, we're gonna add some new permissions to this role.
    1. If you want to play it safe, you can set it up so Lambda can only access that specific DynamoDB table. You'll need to use the table's ARN for this.
    1. If you're feeling a bit lazy like me, you can just give it full access to DynamoDB LOL.

Use DynamoDB sdk in your lambda functions.

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

const client = new DynamoDBClient({});
const dynamo = DynamoDBDocumentClient.from(client);
const tableName = "expressDB";


export const handler = async (event) => {
  try {
    if (event.httpMethod === 'POST') {
      await dynamo.send(
        new PutCommand({
          TableName: tableName,
          Item: { // ... },
        })
      );
      return {
			  statusCode,
			  headers,
			  body: JSON.stringify(body)
			}
    } 
    else {
      return createResponse(400, { message: `Unsupported HTTP method: ${event.httpMethod}` });
    }
  } catch (error) {
    console.error("Error:", error);
    return createResponse(500, { message: "Internal server error", error: error.toString() });
  }
};

Some Notes

Finding 1

Why do I still run into CORS issues with Lambda even when I've fully enabled CORS in API Gateway?

Even with CORS enabled in API Gateway, your Lambda function needs to play ball too. Here's why:

  • API Gateway's CORS settings mainly handle preflight (OPTIONS) requests.
  • For actual GET, POST, etc., requests, your Lambda needs to send the right CORS headers.

Quick fix

// CORS headers
const headers = {
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Headers': 'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token',
  'Access-Control-Allow-Methods': 'OPTIONS,POST,GET'
};

"
// for every response
return createResponse(200, { message: "Session saved successfully" });

Thought 2

When you change something in API Gateway, always remember

"Deploy API"

EOF