Run a standard library net/http handler on AWS Lambda without rewriting it for
the Lambda event model.
The package wraps any http.Handler and translates between AWS Lambda events and
net/http in-process: it converts the incoming event into an *http.Request,
runs your handler against a buffering ResponseWriter, and converts the buffered
result back into a Lambda response. Your handler stays completely unaware that it
is running on Lambda.
Supported event source: API Gateway HTTP API (payload format v2) and Lambda Function URLs (
events.APIGatewayV2HTTPRequest). Other sources (REST v1, ALB) are not handled yet — see Roadmap.
go get github.com/iadams749/go-lambda-http-wrapperpackage main
import (
"fmt"
"net/http"
lambdahttp "github.com/iadams749/go-lambda-http-wrapper"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("GET /hello", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "hello world")
})
// Start blocks, serving Lambda invocations through the mux.
lambdahttp.New(mux).Start()
}New returns an *Adapter. Start hands it to lambda.Start; if you need the
handler function directly (for custom wiring or testing) use Proxy:
adapter := lambdahttp.New(mux)
resp, err := adapter.Proxy(ctx, event) // events.APIGatewayV2HTTPRequest -> events.APIGatewayV2HTTPResponse- Request translation — method, path, raw query string (including
multi-value params), headers, and cookies (rejoined from the v2
Cookiesfield into aCookieheader). - Body handling — base64-encoded request bodies are decoded automatically.
- Response translation — status (defaulting to
200), headers, and body. MultipleSet-Cookieheaders are routed to the v2 responseCookiesfield. - Binary responses — bodies are base64-encoded (with
isBase64Encodedset) when theContent-Typeis non-textual, falling back to a UTF-8 check when no type is present. - Panic recovery — a panic in the handler is logged (with its stack trace)
and becomes a
500response instead of crashing the invocation. Recovered panics and rejected events are reported throughslog.Default(), or a logger of your choice viaWithLogger. - Access to the raw event — retrieve the original event from the request context for data with no HTTP equivalent (authorizer claims, stage variables, request context).
func handler(w http.ResponseWriter, r *http.Request) {
if event, ok := lambdahttp.RequestEvent(r.Context()); ok {
claims := event.RequestContext.Authorizer.JWT.Claims
_ = claims
}
}When the API is served under a custom domain base path the handler should not
see, strip it with WithBasePath:
lambdahttp.New(mux, lambdahttp.WithBasePath("/api")).Start()
// a request to /api/users reaches the handler as /usersThe prefix only matches whole path segments: with base path /api, a request
to /apiv2/users is passed through unchanged.
Common tasks are wrapped in the Makefile:
| Target | Description |
|---|---|
make test |
Run unit tests with the race detector + cover |
make cover |
Write a coverage profile and open the report |
make check |
Verify formatting (fmt) and run go vet |
make tidy |
Sync go.mod / go.sum |
CI runs the same checks plus golangci-lint and
govulncheck on every
push to main and every pull request, and uploads coverage to Codecov.
- Additional event sources: API Gateway REST v1, ALB target groups.
- Response streaming.
- A local development server that speaks the same translation for
go run. - Framework adapter helpers.