lambdahttp

package module
v0.0.0-...-79bd200 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 22, 2026 License: MIT Imports: 11 Imported by: 0

README

go-lambda-http-wrapper

CI codecov Go Reference

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.

Install

go get github.com/iadams749/go-lambda-http-wrapper

Quick start

package 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

Features

  • Request translation — method, path, raw query string (including multi-value params), headers, and cookies (rejoined from the v2 Cookies field into a Cookie header).
  • Body handling — base64-encoded request bodies are decoded automatically.
  • Response translation — status (defaulting to 200), headers, and body. Multiple Set-Cookie headers are routed to the v2 response Cookies field.
  • Binary responses — bodies are base64-encoded (with isBase64Encoded set) when the Content-Type is 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 500 response instead of crashing the invocation. Recovered panics and rejected events are reported through slog.Default(), or a logger of your choice via WithLogger.
  • 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).
Accessing the original event
func handler(w http.ResponseWriter, r *http.Request) {
	if event, ok := lambdahttp.RequestEvent(r.Context()); ok {
		claims := event.RequestContext.Authorizer.JWT.Claims
		_ = claims
	}
}
Stripping a base path

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 /users

The prefix only matches whole path segments: with base path /api, a request to /apiv2/users is passed through unchanged.

Development

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.

Roadmap

  • 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.

License

MIT

Documentation

Overview

Package lambdahttp adapts a standard library http.Handler so it can serve AWS Lambda requests originating from API Gateway HTTP APIs (payload format v2) or Lambda Function URLs.

The adapter is a bidirectional translator: it converts the incoming Lambda event into an *http.Request, runs your handler against a buffering ResponseWriter, and converts the buffered result back into a Lambda response. Your handler code stays completely unaware that it is running on Lambda.

func main() {
	mux := http.NewServeMux()
	mux.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintln(w, "hello world")
	})
	lambdahttp.New(mux).Start()
}

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func RequestEvent

func RequestEvent(ctx context.Context) (events.APIGatewayV2HTTPRequest, bool)

RequestEvent returns the original API Gateway v2 event associated with the request context, if present. Handlers can use it to reach data that has no http.Request equivalent, such as authorizer claims, stage variables, or the full request context.

func handler(w http.ResponseWriter, r *http.Request) {
	if event, ok := lambdahttp.RequestEvent(r.Context()); ok {
		// event.RequestContext.Authorizer.JWT.Claims, etc.
	}
}

Types

type Adapter

type Adapter struct {
	// contains filtered or unexported fields
}

Adapter wraps an http.Handler so it can serve AWS Lambda requests originating from API Gateway HTTP APIs (payload format v2) or Lambda Function URLs.

func New

func New(handler http.Handler, opts ...Option) *Adapter

New wraps an http.Handler in an Adapter.

func (*Adapter) Proxy

Proxy translates a Lambda event into an *http.Request, runs the wrapped handler, and translates the buffered result back into a Lambda response. Its signature satisfies lambda.Start.

A panic in the handler is recovered, logged with its stack trace via slog, and reported to the caller as a 500 response rather than crashing the Lambda invocation. An event whose body cannot be decoded is logged and answered with a 400 without invoking the handler; in both cases the returned error is nil so the invocation itself still succeeds.

func (*Adapter) Start

func (a *Adapter) Start()

Start hands the adapter to lambda.Start, using Proxy as the invocation handler. It blocks until the Lambda runtime shuts the process down.

type Option

type Option func(*Adapter)

Option configures an Adapter.

func WithBasePath

func WithBasePath(basePath string) Option

WithBasePath strips the given prefix from the request path before the request reaches the handler. This is useful when the API is served under a custom domain base path (for example "/api") that the handler should not see. The prefix only matches on segment boundaries: "/api" strips "/api/users" but leaves "/apiv2/users" untouched. A trailing slash on basePath is ignored.

func WithLogger

func WithLogger(logger *slog.Logger) Option

WithLogger sets the logger the adapter uses to report recovered panics and rejected events. When not set, slog.Default() is used.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL