Skip to content

HTTP event handler

Route API Gateway, ALB and Lambda Function URL requests with path parameters, JSON responses and middleware.

Install

Use Go 1.27 or newer:

CGO_ENABLED=0 go get github.com/rambow-cloud/powertools-lambda-go/eventhandler/http@v1.2.0
CGO_ENABLED=0 go get github.com/rambow-cloud/powertools-lambda-go/logger@v1.2.0
CGO_ENABLED=0 go get github.com/aws/aws-lambda-go@v1.55.0

Import the routing module as httpapi to distinguish it from the standard library's net/http.

Return an order as JSON

Register a GET route once, then pass Lambda events to Resolve. Connect the function to an HTTP proxy integration or a Function URL.

Input

GET /orders/ORD-123

Code

package main

import (
    "context"
    "encoding/json/jsontext"
    "os"

    "github.com/aws/aws-lambda-go/lambda"
    httpapi "github.com/rambow-cloud/powertools-lambda-go/eventhandler/http"
    "github.com/rambow-cloud/powertools-lambda-go/logger"
)

func main() {
    appLog := logger.New(logger.WithServiceName("orders"))
    if err := run(appLog); err != nil {
        if logErr := appLog.Error("Application failed", err); logErr != nil {
            panic(logErr)
        }
        os.Exit(1)
    }
}

func run(appLog *logger.Logger) error {
    app := httpapi.New(httpapi.Options{})
    err := app.Get("/orders/:id", func(request *httpapi.RequestContext) (any, error) {
        return map[string]string{"id": request.Params["id"]}, nil
    })
    if err != nil {
        return err
    }
    lambda.Start(func(ctx context.Context, event jsontext.Value) (httpapi.ProxyResponse, error) {
        return app.Resolve(ctx, event)
    })
    return nil
}

Output

HTTP/1.1 200 OK
Content-Type: application/json

{"id":"ORD-123"}

Read JSON and return a status code

Save this as orders.go beside the application above. In run, call registerCreateOrder(app) after creating the router and return any registration error before starting Lambda.

package main

import (
    json "encoding/json/v2"

    httpapi "github.com/rambow-cloud/powertools-lambda-go/eventhandler/http"
)

func registerCreateOrder(app *httpapi.Router) error {
    return app.Post("/orders", func(request *httpapi.RequestContext) (any, error) {
        var order struct {
            Name string `json:"name"`
        }
        if err := json.UnmarshalRead(request.Request.Body, &order); err != nil {
            return nil, httpapi.NewHTTPError(400, "Expected a JSON order")
        }
        if order.Name == "" {
            return nil, httpapi.NewHTTPError(400, "name is required")
        }
        return httpapi.Response{StatusCode: 201, Body: order}, nil
    })
}

The JSON decoder is imported explicitly from encoding/json/v2.

Request → response

POST /orders  {"name":"Notebook"}  →  201 {"name":"Notebook"}
POST /orders  {}                   →  400, "name is required"

Read request values

Value Go expression
Path parameter request.Params["id"]
Query string request.Request.URL.Query().Get("status")
Header request.Request.Header.Get("Authorization")
JSON body json.UnmarshalRead(request.Request.Body, &value)

Test with a Lambda event

For API Gateway v2 or a Function URL, a console test can use:

{
  "version": "2.0",
  "rawPath": "/orders/ORD-123",
  "rawQueryString": "",
  "headers": {},
  "requestContext": {
    "domainName": "example.test",
    "stage": "$default",
    "http": {
      "method": "GET",
      "path": "/orders/ORD-123",
      "protocol": "HTTP/1.1",
      "sourceIp": "127.0.0.1",
      "userAgent": "docs"
    }
  },
  "routeKey": "$default",
  "isBase64Encoded": false
}

Lambda returns a proxy envelope whose body is a JSON string. The HTTP caller receives the decoded body shown above.

Add more behavior

Things to know

  • Check route-registration errors before starting Lambda.
  • A missing route returns a not-found response. Use NewHTTPError for expected HTTP failures.
  • Reuse the router; keep per-request values in the request/context rather than shared mutable variables.

Next steps

See the API and behavior notes for advanced options, and module installation for dependencies.