[Cloud DA] Serverless Framework with AWS - Part 1: DynamoDB & ApiGateway

Part 1 Of Serverless Framework with AWS

DynamoDB & ApiGateway

Build a Lambda function get data from DynamoDB:

src/lambda/http/getGroups.ts

import * as AWS from "aws-sdk";
import {
  APIGatewayProxyEvent,
  APIGatewayProxyHandler,
  APIGatewayProxyResult,
} from "aws-lambda";

const docClient = new AWS.DynamoDB.DocumentClient();
const groupTables = process.env.GROUPS_TABLE;

export const handler: APIGatewayProxyHandler = async (
  event: APIGatewayProxyEvent
): Promise<APIGatewayProxyResult> => {
const result = await docClient
    .scan({
      TableName: groupTables,
    })
    .promise();

  const items = result.Items;

  return {
    statusCode: 200,
    headers: {
      "Access-Control-Allow-Origin": "*",
    },
    body: JSON.stringify({
      items,
    }),
  };
};

 

serverless.yml:

service:
  name: serverless-udagram-app

plugins:
  - serverless-webpack

provider:
  name: aws
  runtime: nodejs14.x

  stage: ${opt:stage, 'dev'}
  region: ${opt:region, 'us-east-1'}

  environment:
    GROUPS_TABLE: Groups-${self:provider.stage}

  iamRoleStatements:
    - Effect: Allow
      Action:
        - dynamodb:Scan
      Resource: arn:aws:dynamodb:${self:provider.region}:*:table/${self:provider.environment.GROUPS_TABLE}

functions:
  GetGroups:
    handler: src/lambda/http/getGroups.handler
    events:
      - http:
          method: get
          path: groups
          cors: true

resources:
  Resources:
    GroupsDynamoDBTable:
      Type: AWS::DynamoDB::Table
      Properties:
        AttributeDefinitions:
          - AttributeName: id
            AttributeType: S
        KeySchema:
          - AttributeName: id
            KeyType: HASH
        BillingMode: PAY_PER_REQUEST
        TableName: ${self:provider.environment.GROUPS_TABLE}

 

Validate request in ApiGateway

Refer to: https://www.cnblogs.com/Answer1215/p/14774552.html

 

Query in Node.js

const docClient = new AWS.DynamoDB.DocumentClient()

 const result = await docClient.query({
   TableName: 'GameScore',
   KeyConditionExpression: 'GameId = :gameId',
   ExpressionAttributeValues: {
     ':gameId': '10'
   }
 }).promise()

 const items = result.Items

 

Path parameter

functions:
    GetOrders:
      handler: src/images.handler
      events:
        - http:
            method: get
            path: /groups/{groupId}/images
export.handler = async (event) => {
  const grouId = event.pathParameters.groupId;
  ...
}

 

Add indexes

serverless.yml

service:
  name: serverless-udagram-app

plugins:
  - serverless-webpack

provider:
  name: aws
  runtime: nodejs14.x

  stage: ${opt:stage, 'dev'}
  region: ${opt:region, 'us-east-1'}

  environment:
    GROUPS_TABLE: Groups-${self:provider.stage}
    IMAGES_TABLE: Images-${self:provider.stage}
    IMAGE_ID_INDEX: ImageIdIndex

  iamRoleStatements:
    - Effect: Allow
      Action:
        - dynamodb:Query
      Resource: arn:aws:dynamodb:${self:provider.region}:*:table/${self:provider.environment.IMAGES_TABLE}/index/${self:provider.environment.IMAGE_ID_INDEX}
    - Effect: Allow
      Action:
        - dynamodb:Query
        - dynamodb:PutItem
      Resource: arn:aws:dynamodb:${self:provider.region}:*:table/${self:provider.environment.IMAGES_TABLE}
    - Effect: Allow
      Action:
        - dynamodb:Scan
        - dynamodb:PutItem
        - dynamodb:GetItem
      Resource: arn:aws:dynamodb:${self:provider.region}:*:table/${self:provider.environment.GROUPS_TABLE}

functions:
  CreateImage:
    handler: src/lambda/http/createImage.handler
    events:
      - http:
          method: post
          path: groups/{groupId}/images
          cors: true
          reqValidatorName: RequestBodyValidator
          request:
            schema:
              application/json: ${file(models/create-image-request.json)}
  GetImage:
    handler: src/lambda/http/getImage.handler
    events:
      - http:
          method: get
          path: images/{imageId}
          cors: true
  GetImages:
    handler: src/lambda/http/getImages.handler
    events:
      - http:
          method: get
          path: group/{groupId}/images
          cors: true
  GetGroups:
    handler: src/lambda/http/getGroups.handler
    events:
      - http:
          method: get
          path: groups
          cors: true
  CreateGroup:
    handler: src/lambda/http/createGroup.handler
    events:
      - http:
          method: post
          path: groups
          cors: true
          ## do the validation in api gateway
          reqValidatorName: RequestBodyValidator
          request:
            schema:
              application/json: ${file(models/create-group-request.json)}

resources:
  Resources:
    ImagesDynamoDBTable:
      Type: AWS::DynamoDB::Table
      Properties:
        TableName: ${self:provider.environment.IMAGES_TABLE}
        BillingMode: PAY_PER_REQUEST
        KeySchema:
          - AttributeName: groupId
            KeyType: HASH
          - AttributeName: timestamp
            KeyType: RANGE
        AttributeDefinitions:
          - AttributeName: groupId
            AttributeType: S
          - AttributeName: timestamp
            AttributeType: S
          - AttributeName: imageId
            AttributeType: S
        GlobalSecondaryIndexes:
          - IndexName: ${self:provider.environment.IMAGE_ID_INDEX}
            KeySchema:
              - AttributeName: imageId
                KeyType: HASH
            ## Copy all the attrs to the new GSI table
            Projection:
              ProjectionType: ALL

    GroupsDynamoDBTable:
      Type: AWS::DynamoDB::Table
      Properties:
        AttributeDefinitions:
          - AttributeName: id
            AttributeType: S
        KeySchema:
          - AttributeName: id
            KeyType: HASH
        BillingMode: PAY_PER_REQUEST
        TableName: ${self:provider.environment.GROUPS_TABLE}
const docClient = new AWS.DynamoDB.DocumentClient();
const imagesTable = process.env.IMAGES_TABLE;
const imageIdIndex = process.env.IMAGE_ID_INDEX;

export const handler: APIGatewayProxyHandler = async (
  event: APIGatewayProxyEvent
): Promise<APIGatewayProxyResult> => {
  const imageId = event.pathParameters.imageId;
  const result = await docClient
    .query({
      TableName: imagesTable,
      IndexName: imageIdIndex,
      KeyConditionExpression: "imageId= :imageId",
      ExpressionAttributeValues: {
        ":imageId": imageId,
      },
    })
    .promise();

 

posted @ 2021-05-24 22:12  Zhentiw  阅读(114)  评论(0编辑  收藏  举报