Creating aws serverless api using golang cdk
How to create a serverless API on AWS, using API Gateway, Lambda in Go CDK
Creating AWS Serverless Api Using Golang cdk
Pre-Reqs:
- Go installed
- lambda function ready to deploy
- AWS account
- AWS cli configured
Golang cdk quirks
Golang does not have null, so to prevent any breaking changes, aws uses jsii type library. jsii achieves cross-language communication in AWS CDK by generating language-specific bindings and glue code during the build process, ensuring consistent type systems and enabling developers to express infrastructure components in their language of choice while maintaining interoperability with other supported languages.
Creating cdk app
The cdk init command cannot be executed in a non empty directory, so create a directory for your cdk app and run the initialisation command:
1cdk init app --language go
This creates your cdk project structure.
To install default aws cdk dependencies, run:
1go get
To install dependancies for api gateway and lambda cdks, run:
1go get github.com/aws/aws-cdk-go/awscdk/v2/awsapigateway 2go get github.com/aws/aws-cdk-go/awscdk/v2/awslambda
Configuring environment
Creating an API Gateway
In the NewCdkStack method call NewRestAPI from awsapigateway with the stack, api gateway name and an optional props object. I have just used nil.
1api := awsapigateway.NewRestApi(stack, jsii.String("fpl-intel-cdk"), nil)
The error is because the api is not being used (yet)
Creating the Lambda function
I have created a function that creates & returns a new rust lambda. Any AWS Lambda runtime can be chosen. The lambdaBuilddirectory & lambdaBuildZip are for the example hello world rust lambda, found in the Github repository
1type LambdaData struct { 2 name string 3 httpMethods string 4} 5 6func CreateNewRustLambdaFunction(lambdaConfig LambdaData, stack awscdk.Stack) awslambda.Function { 7 lambdaBuildDirectory := "../hello-world/target/lambda/" 8 lambdaBuildZip := "/bootstrap.zip" 9 10 return awslambda.NewFunction(stack, jsii.String(lambdaConfig.name), &awslambda.FunctionProps{ 11 Runtime: awslambda.Runtime_PROVIDED_AL2(), 12 Code: awslambda.Code_FromAsset(jsii.String(lambdaBuildDirectory+lambdaConfig.name+lambdaBuildZip), nil), 13 Handler: jsii.String("bootstrap"), 14 MemorySize: jsii.Number(128), 15 Timeout: awscdk.Duration_Seconds(jsii.Number(30)), 16 }) 17}
Use this function in NewCdkStack to create a new lambda
1helloWorldLambda := CreateNewRustLambdaFunction(helloWorldLambdaData, stack)
Connecting the Lambda function to API Gateway
I have created a function that takes in any aws lambda function and adds it to the api gateway, with open cors for a GET
request. The resource name is the path, so to hit the endpoint, it will be
1func AddLambdaToApiGateway(lambdaFunction awslambda.Function, lambdaConfig LambdaData, api awsapigateway.RestApi) { 2 resource := api.Root().AddResource(jsii.String(lambdaConfig.name), nil) 3 apiIntegration := awsapigateway.NewLambdaIntegration(lambdaFunction, &awsapigateway.LambdaIntegrationOptions{ 4 Proxy: jsii.Bool(true), 5 }) 6 7 corsOptions := &awsapigateway.CorsOptions{ 8 AllowOrigins: awsapigateway.Cors_ALL_ORIGINS(), 9 AllowMethods: awsapigateway.Cors_ALL_METHODS(), 10 } 11 resource.AddCorsPreflight(corsOptions) 12 resource.AddMethod(jsii.String("GET"), apiIntegration, nil) 13}
Use this function in NewCdkStack to connect the lambda with the api gateway
1AddLambdaToApiGateway(helloWorldLambda, helloWorldLambdaData, api)
Final cdkNewStack method
1func NewCdkStack(scope constructs.Construct, id string, props *CdkStackProps) awscdk.Stack { 2 var sprops awscdk.StackProps 3 if props != nil { 4 sprops = props.StackProps 5 } 6 stack := awscdk.NewStack(scope, &id, &sprops) 7 8 api := awsapigateway.NewRestApi(stack, jsii.String("fpl-intel-cdk"), nil) 9 10 helloWorldLambdaData := LambdaData{ 11 name: "hello-world", 12 httpMethods: "GET", 13 } 14 15 helloWorldLambda := CreateNewRustLambdaFunction(helloWorldLambdaData, stack) 16 AddLambdaToApiGateway(helloWorldLambda, helloWorldLambdaData, api) 17 18 return stack 19}
Deploying
Simply execute the cdk deploy command in your cdk directory
1cdk deploy
If you need to use a certain profile, use
1cdk deploy --profile profile_name
Example Deployment
Tear down
To prevent any cost surprises it is best to tear down any cdk deployments you no longer wish to keep seployed
1cdk destroy