Step by Step to deploy Go API on AWS lambda and access by function URL
Tags: go, api, aws
Published: 2024-05-24 16:22:56

## Introduction

In today's world of cloud computing,  [AWS Lambda](https://aws.amazon.com/lambda) is a serverless, event-driven compute service that lets you run code for virtually any type of application or backend service without provisioning or managing servers. You can trigger Lambda from over 200 AWS services and software as a service (SaaS) applications, and only pay for what you use.

Go is a statically typed, compiled language known for its simplicity, efficiency, and ease of use. It's particularly well-suited for building scalable and efficient cloud services.

In this guide, I will demonstrate how to deploy a Go API server on AWS Lambda step by step.

## Creating a Lambda Function

First, you need to create a new Lambda function. Log into your AWS console and navigate to the Lambda service. Click the 'Create function' button. You will see many options, but don't worry, we only need to adjust a few. Leaving the rest as they are will be sufficient to host our Go server.

- Enter your function name. For example, I used `go-api`. You should use a name that is meaningful.
- Select the runtime. In this case, we'll choose `Amazon Linux 2023`.
- Optionally, if you're building a Go application for ARM, you should change the Architecture to arm64.

![create aws lambda](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1uinhhkbycobnbnug37e.png)

- Click to open Advanced settings and enable the `function URL`. This function is powerful and easy to use, and we will be using it.
- Setting the `Auth type` to `NONE` simplifies its use. For enhanced security, you could use `AWS_IAM`, but that's a different topic that we won't discuss here.

![setting function URL](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/brxn9083vp7kpu40ajor.png)

## Edit the Go Source Code

Next, we need to create a minimal Go function for AWS Lambda. Here's a sample `main.go`.

- We import `github.com/aws/aws-lambda-go/lambda`. This dependency is necessary for running Go as a Lambda function.
- In the `main` function, we use `lambda.Start` to start the handler.

```go
package main

import (
	"context"
	"fmt"
	"github.com/aws/aws-lambda-go/lambda"
)

type RequestEvent struct {
	RawPath        string `json:"rawPath"`
	RawQueryString string `json:"rawQueryString"`
	Body           string `json:"body"`
}

func HandleRequest(ctx context.Context, event *RequestEvent) (*string, error) {
	if event == nil {
		return nil, fmt.Errorf("received nil event")
	}
	message := fmt.Sprintf(
		"RawPath: %s, RawQueryString: %s, Body: %s",
		event.RawPath, event.RawQueryString, event.Body,
	)
	return &message, nil
}

func main() {
	lambda.Start(HandleRequest)
}
```

Next, we need to compile the main into a binary. Simply copy the following command line, ensuring the output filename is 'bootstrap'.

```bash
GOOS=linux GOARCH=amd64 go build -tags lambda.norpc -o bootstrap main.go
```

Next, we need to compress the bootstrap file into a zip format. Without doing this, we cannot upload it to AWS Lambda. Be sure to place the bootstrap file at the root of the zip file.

```bash
zip myFunction.zip bootstrap
```

We've now set up the basic Go application. It's time to upload and conduct a test.

## Upload to AWS lambda

Click to enter the lambda function we created previously and scroll down. Find the `Code Source` block within the code tab. To the right of this block, click the `Upload from` button and select the `.zip file` option. Locate your zip file and upload it.

![upload zip file](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/028086lxxag0inige63x.png)

After uploading, you should find information similar to the details below the `Code Source` block. This indicates that your upload was successful.

![code information](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xgehpdj9zo3aitwd4bdo.png)

## Test the function

Scroll up, and on the right of `Function overview`, you'll find the `function URL`. This is the advanced option we just set. The `function URL` is a powerful tool that can convert your RESTful requests into lambda handler requests, and then encode the handler output into a RESTful response. It's particularly useful for building API servers based on lambda.

![copy function URL](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7pkux99umirrbo1ozoxd.png)

Click the small copy button to duplicate the URL. You can now use `curl` to test your lambda function. Input this command into your terminal and press enter. Remember, you need to replace the `function URL` with your own.

```bash
curl -XPOST 'https://{your_lambda_function_URL}/hello?
name=world' -H 'Content-Type: application/json' --data '{"age": 16}'
```

The magic happens, you should see the output like this:

```
RawPath: /hello, RawQueryString: name=world, Body: {"age": 16}
```

Review the codes again, and you'll find the structure. This structure is the second parameter of the handler. The magic here is that the lambda library decodes the path, query string, and body into our structure. While many other fields are available, these three are the most crucial.

```go
type RequestEvent struct {
	RawPath        string `json:"rawPath"`
	RawQueryString string `json:"rawQueryString"`
	Body           string `json:"body"`
}
```

## Reference

1. **[Building Lambda functions with Go](https://docs.aws.amazon.com/lambda/latest/dg/lambda-golang.html)** 
2. **[Lambda function URLs](https://docs.aws.amazon.com/lambda/latest/dg/lambda-urls.html)**