How do I run existing Go applications on AWS Lambda - Part 1
Learn how to run Go REST APIs as Lambda functions using the AWS Lambda Go API Proxy.
Abhishek Gupta
Amazon Employee
Published Jul 20, 2023
Last Modified Mar 14, 2024
The Go programming language has always had rich support for building REST APIs. This includes an excellent standard library (net/http) along with many popular packages such as gorilla mux, Gin, negroni, echo, fiber etc.
Thanks to the AWS Lambda Go runtime, you can use Go to build AWS Lambda functions. Imagine a web app that needs to authenticate users, store user data, and send emails. A Serverless approach for this would to implement each functionality/API as a separate Lambda function. For example, you could have a Lambda function to handle user registration, another to handle user login, and so on.
This is great if you are building everything from scratch. But what if you wanted to run existing Go REST APIs as AWS Lambda functions?
Broadly speaking, you would need to:
Broadly speaking, you would need to:
- Split the existing code into multiple Lambda functions.
- Refactor each of them to work with AWS Lambda Go runtime APIs.
With the AWS Lambda Go API Proxy, there is an easier way!
This blog will demonstrate how to run existing Go frameworks based APIs in a serverless way with AWS Lambda and Amazon API Gateway. You will walk through simple code examples for
net/http
package, gorilla
and echo
framework to understand how they work and deploy them using AWS Serverless Application Model.The code is available in this GitHub repository
Let's start with a brief introduction to the AWS Lambda Go API Proxy.
The aws-lambda-go-api-proxy package makes it easy to run Go APIs written using frameworks (such as Gin) with AWS Lambda and Amazon API Gateway. In addition to adapter implementations for the
net/http
(Go standard library) and other frameworks such as gorilla/mux
, echo
, etc., aws-lambda-go-api-proxy
also declares a core
package that contains utility methods and interfaces to translate API Gateway proxy events into Go's default http.Request
and http.ResponseWriter
objects and allows you to adapt any framework to the AWS Lambda Go runtime.Here is a gist on how it works at a high level:
- The API Gateway request is accepted by the Lambda function handler.
- The function handler proxies the request to the adapter implementation corresponding to the framework.
- Finally, the API Gateway proxy response is returned to the client.
Let's look into the framework specific behavior.
Package
gorilla/mux
implements a request router and dispatcher for matching incoming requests to their respective handler. Like http.ServeMux
in the Go standard library, mux.Router
matches incoming requests against a list of registered routes and calls a handler for the route that matches the URL or other conditions. Because gorilla/mux
implements the http.Handler
interface, it is compatible with http.ServeMux
.Here is a simple example of a Lambda function that uses an adapter implementation to work with
gorilla/mux
package:- In the
init
function:gorillamux.New
function takes in amux.Router
(which has theHTTP
GET
route defined) and returns agorillamux.GorillaMuxAdapter
. - In the
Handler
implementation:- The
Proxy
(orProxyWithContext
) method of thegorillamux.GorillaMuxAdapter
object receives theevents.APIGatewayProxyRequest
, converts it into ahttp.Request
object, and sends it to themux.Router
for routing. - It returns a proxy response object (
events.APIGatewayProxyResponse
) generated from the data written to the response writer (http.ResponseWriter
).
Echo another popular Go web framework which is minimalist, yet highly extensible.
Here is a simple example of a Lambda function that uses an adapter implementation to work with the
echo
framework:The concept is similar to the previous example.
- The
init
function sets up the router (echo.Echo
) and passes it into theechoadapter.New
thar returns aechoadapter.EchoLambda
(the adapter implementation). - In the
Handler
function:- The
ProxyWithContext
method of theechoadapter.EchoLambda
object receives theevents.APIGatewayProxyRequest
object and converts it into anhttp.Request
object and sends it toecho.Echo
for routing. - It returns a proxy response object (
events.APIGatewayProxyResponse
) generated from the data written to the response writer (http.ResponseWriter
).
The adapter implementation for
net/http
also works the same way. Here is the code snippet:- To use with the standard library, the
httpadapter.New
function takes in ahttp.Handler
(which has the route defined) and returns ahttpadapter.HandlerAdapter
object. - The
ProxyWithContent
method on thehttpadapter.HandlerAdapter
can then be used as a Lambda handler.
Let's see how this works in practice.
Let's deploy each of these functions to AWS Lambda using the SAM CLI.
Before you proceed, make sure you have the Go programming language (v1.18 or higher) and AWS SAM installed.
Clone the project and change to the right directory:
First, update the
CodeUri
in template.yaml
to gorilla/
(which is the local folder where the code is located).Build the function:
Deploy the function (follow the SAM CLI prompts):
Once the deployment is complete, navigate to AWS
CloudFormation
console to check the deployed stack and associated resources. These include the Lambda function, API Gateway (REST API), IAM role, etc.You should see the API Gateway endpoint as the SAM CLI output (it will be different in your case) or the
CloudFormation
Outputs section.To test the function, invoke the API Gateway using the following command:
You should get a
JSON
response similar to the following:Before you deploy either of these, make sure to update the
CodeUri
in template.yaml
to refer to the local folder where the code is located:http-stdlib/
in case ofnet/http
package.echo/
in case ofecho
framework.
Build and deploy the function (respond to the prompts, just like before):
You can test the function by invoking the API Gateway endpoint:
You should get a
JSON
response similar to the following:In case of
echo
framework, you should get a JSON
response similar to the following (notice the different name in the from
field):That's it! You have successfully deployed your Go APIs as AWS Lambda functions.
Once you are done, delete the stacks:
This blog post introduced you to the AWS Lambda Go API Proxy, and how it's framework/package (for
gorilla/mux
, echo
and net/http
) specific adapter implementations allow you to run existing Go applications as AWS Lambda functions fronted by an API Gateway. You learned the basic concepts with simple code examples, deployed these functions using AWS SAM CLI and verified it by invoking the API Gateway endpoint.The AWS Lambda Go API Proxy also supports the Gin, which one of the most popular Go web frameworks! The second part of this blog, will demonstrate how to run existing
Gin
framework based Go applications as AWS Lambda functions with the help of a simple (yet practical) URL shortener service.Stay tuned!
Any opinions in this post are those of the individual author and may not reflect the opinions of AWS.