API Gateway REST API to Lambda to DynamoDB

Create a Lambda function that receives a request from API Gateway and puts an item into DynamoDB.

API GatewayAWS LambdaAmazon DynamoDB
package main

import (
	"github.com/aws/aws-cdk-go/awscdk/v2"
	"github.com/aws/aws-cdk-go/awscdk/v2/awsapigateway"
	"github.com/aws/aws-cdk-go/awscdk/v2/awsdynamodb"
	"github.com/aws/aws-cdk-go/awscdk/v2/awsiam"
	"github.com/aws/aws-cdk-go/awscdk/v2/awslambda"
	"github.com/aws/constructs-go/constructs/v10"
	"github.com/aws/jsii-runtime-go"
)

type ApigwLambdaDynamodbCdkGolangStackProps struct {
	awscdk.StackProps
}

// DynamoDB related constants
const (
	tableName               = "users-table"
	partitionKeyName        = "email"
	dynamoDBTableNameEnvVar = "DYNAMODB_TABLE_NAME"
)

// Lambda function related constants
const (
	lambdaHandlerName   = "my-func" //same as Go binary name
	functionZipFilePath = "../function/function.zip"
)

// API Gateway related constants
const (
	apigwResourceName = "users"
	httpMethod        = "POST"
)

func NewApigwLambdaDynamodbCdkGolangStack(scope constructs.Construct, id string, props *ApigwLambdaDynamodbCdkGolangStackProps) awscdk.Stack {
	var sprops awscdk.StackProps
	if props != nil {
		sprops = props.StackProps
	}
	stack := awscdk.NewStack(scope, &id, &sprops)

	// DynamoDB partition key
	partitionKey := &awsdynamodb.Attribute{Name: jsii.String(partitionKeyName), Type: awsdynamodb.AttributeType_STRING}

	// DynamoDB table
	dynamoDBTable := awsdynamodb.NewTable(stack, jsii.String("dynamodb-table"), &awsdynamodb.TableProps{TableName: jsii.String(tableName), BillingMode: awsdynamodb.BillingMode_PAY_PER_REQUEST, PartitionKey: partitionKey, RemovalPolicy: awscdk.RemovalPolicy_DESTROY})

	// environment variable for Lambda function
	lambdaEnvVar := &map[string]*string{dynamoDBTableNameEnvVar: dynamoDBTable.TableName()}

	// lambda function packaged as zip file
	function := awslambda.NewFunction(stack, jsii.String("lambda-function"), &awslambda.FunctionProps{Runtime: awslambda.Runtime_GO_1_X(), Handler: jsii.String(lambdaHandlerName), Code: awslambda.AssetCode_FromAsset(jsii.String(functionZipFilePath), nil), Environment: lambdaEnvVar})

	// policy to allow DynamoDB PutItem calls
	dynamoDBPutItemPolicy := awsiam.NewPolicy(stack, jsii.String("policy"), &awsiam.PolicyProps{PolicyName: jsii.String("LambdaDynamoDBPutItemPolicy"), Statements: &[]awsiam.PolicyStatement{awsiam.NewPolicyStatement(&awsiam.PolicyStatementProps{Effect: awsiam.Effect_ALLOW, Actions: jsii.Strings("dynamodb:PutItem"), Resources: jsii.Strings(*dynamoDBTable.TableArn())})}})

	// attach the policy to an IAM role which is created during Lambda creation
	function.Role().AttachInlinePolicy(dynamoDBPutItemPolicy)

	// API Gateway REST API
	restapi := awsapigateway.NewRestApi(stack, jsii.String("rest-apigw"), &awsapigateway.RestApiProps{EndpointTypes: &[]awsapigateway.EndpointType{awsapigateway.EndpointType_REGIONAL}, RestApiName: jsii.String("apigw-users")})

	// explict method definition (instead of proxy)
	restapi.Root().AddMethod(jsii.String(httpMethod), awsapigateway.NewLambdaIntegration(function, &awsapigateway.LambdaIntegrationOptions{AllowTestInvoke: jsii.Bool(false)}), restapi.Root().DefaultMethodOptions())

	return stack
}

func main() {
	app := awscdk.NewApp(nil)

	NewApigwLambdaDynamodbCdkGolangStack(app, "ServerlessCDKGoStack", &ApigwLambdaDynamodbCdkGolangStackProps{
		awscdk.StackProps{
			Env: env(),
		},
	})

	app.Synth(nil)
}

// env determines the AWS environment (account+region) in which our stack is to
// be deployed. For more information see: https://docs.aws.amazon.com/cdk/latest/guide/environments.html
func env() *awscdk.Environment {
	return nil
}

Download

git clone https://github.com/aws-samples/serverless-patterns
cd serverless-patterns/apigw-lambda-dynamodb-cdk-go

Pattern repository

View on GitHub

Last updated on 26 Dec 2024

Edit this page