LF Notice: this is a fork of github.com/awslabs/aws-lambda-go-api-proxy that contains:
- Fix for response headers (current master branch in upstream is broken)
- Fix for query parameters (current master branch in upstream and previous versions is broken)
aws-lambda-go-api-proxy
makes it easy to run Golang APIs written with frameworks such as Gin with AWS Lambda and Amazon API Gateway.
make setup deps build test
# TODO: the code needs cleanup
make lint
The first step is to install the required dependencies
# First, we install the Lambda go libraries
$ go get github.com/aws/aws-lambda-go/events
$ go get github.com/aws/aws-lambda-go/lambda
# Next, we install the core library
$ go get github.com/awslabs/aws-lambda-go-api-proxy/...
Following the instructions from the Lambda documentation, we need to declare a Handler
method for our main package. We will declare a ginadapter.GinLambda
object
in the global scope, initialized once it in the Handler with all its API methods, and then use the Proxy
method to translate requests and responses
package main
import (
"log"
"context"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
"github.com/awslabs/aws-lambda-go-api-proxy/gin"
"github.com/gin-gonic/gin"
)
var ginLambda *ginadapter.GinLambda
func init() {
// stdout and stderr are sent to AWS CloudWatch Logs
log.Printf("Gin cold start")
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
ginLambda = ginadapter.New(r)
}
func Handler(ctx context.Context, req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
// If no name is provided in the HTTP request body, throw an error
return ginLambda.ProxyWithContext(ctx, req)
}
func main() {
lambda.Start(Handler)
}
This package also supports Negroni, GorillaMux, and plain old HandlerFunc
- take a look at the code in their respective sub-directories. All packages implement the Proxy
method exactly like our Gin sample above.
We have included a SAM template with our sample application. You can use the AWS CLI to quickly deploy the application in your AWS account.
First, build the sample application by running make
from the aws-lambda-go-api-proxy
directory.
$ cd aws-lambda-go-api-proxy
$ make
The make
process should generate a main.zip
file in the sample folder. You can now use the AWS CLI to prepare the deployment for AWS Lambda and Amazon API Gateway.
$ cd sample
$ aws cloudformation package --template-file sam.yaml --output-template-file output-sam.yaml --s3-bucket YOUR_DEPLOYMENT_BUCKET
$ aws cloudformation deploy --template-file output-sam.yaml --stack-name YOUR_STACK_NAME --capabilities CAPABILITY_IAM
Using the CloudFormation console, you can find the URL for the newly created API endpoint in the Outputs
tab of the sample stack - it looks sample like this: https://xxxxxxxxx.execute-api.xx-xxxx-x.amazonaws.com/Prod/pets
. Open a browser window and try to call the URL.
The RequestAccessor
object, and therefore GinLambda
, automatically marshals the API Gateway request context and stage variables objects and stores them in custom headers in the request: X-GinLambda-ApiGw-Context
and X-GinLambda-ApiGw-StageVars
. While you could manually unmarshal the json content into the events.APIGatewayProxyRequestContext
and map[string]string
objects, the library exports two utility methods to give you easy access to the data.
// the methods are available in your instance of the GinLambda
// object and receive the http.Request object
apiGwContext := ginLambda.GetAPIGatewayContext(c.Request)
apiGwStageVars := ginLambda.GetAPIGatewayStageVars(c.Request)
// you can access the properties of the context directly
log.Println(apiGwContext.RequestID)
log.Println(apiGwContext.Stage)
// stage variables are stored in a map[string]string
stageVarValue := apiGwStageVars["MyStageVar"]
The aws-lambda-go-api-proxy
, alongside the various adapters, declares a core
package. The core
package, contains utility methods and interfaces to translate API Gateway proxy events into Go's default http.Request
and http.ResponseWriter
objects.
You can see that the ginlambda.go
file extends the RequestAccesor
struct defined in the request.go
file. RequestAccessor
gives you access to the ProxyEventToHTTPRequest()
method.
The GinLambda
object is initialized with an instance of gin.Engine
. gin.Engine
implements methods defined in the http.Handler
interface.
The Proxy
method of the GinLambda
object simply receives the events.APIGatewayProxyRequest
object and uses the ProxyEventToHTTPRequest()
method to convert it into an http.Request
object. Next, it creates a new ProxyResponseWriter
object (defined in the response.go
) file and passes both request and response writer to the ServeHTTP
method of the gin.Engine
.
The ProxyResponseWriter
exports a method called GetProxyResponse()
to generate an events.APIGatewayProxyResponse
object from the data written to the response writer.
Support for frameworks other than Gin can rely on the same methods from the core
package and swap the gin.Engine
object for the relevant framework's object.
This library is licensed under the Apache 2.0 License.