Rene Nochebuena 2298846280 docs(httpmw): add README.md
Document all four middleware functions (Recover, RequestID, RequestLogger, CORS),
the Logger interface, StatusRecorder, recommended middleware order, and install
instructions.
2026-03-18 19:35:13 -06:00
2026-03-18 19:35:13 -06:00

httpmw

net/http middleware for transport-layer concerns: panic recovery, CORS, request ID injection, and structured request logging.

Overview

Four composable func(http.Handler) http.Handler middleware functions:

Middleware Responsibility
Recover() Catches panics; writes 500; captures stack trace
RequestID(generator) Generates a unique ID; injects it via logz.WithRequestID; sets X-Request-ID header
RequestLogger(logger) Logs method, path, status, latency, and request ID after each request
CORS(origins) Sets CORS headers; short-circuits OPTIONS with 204

No authentication or identity logic lives here — see httpauth-firebase for that.

Install

go get code.nochebuena.dev/go/httpmw

Usage

// Recommended order — outermost middleware first
mux.Use(httpmw.Recover())
mux.Use(httpmw.RequestID(uuid.NewString))
mux.Use(httpmw.RequestLogger(logger))
mux.Use(httpmw.CORS([]string{"https://example.com"}))

Pass []string{"*"} to CORS to allow any origin (development only).

Middleware

Recover

mux.Use(httpmw.Recover())

Wraps the handler in a defer/recover. On panic, writes 500 Internal Server Error and captures debug.Stack(). No logger is required.

RequestID

mux.Use(httpmw.RequestID(uuid.NewString))

Calls generator() on every request, stores the ID with logz.WithRequestID, and writes it to the X-Request-ID response header. Must run before RequestLogger so the ID is in context when the logger reads it.

RequestLogger

mux.Use(httpmw.RequestLogger(logger))

Logs method, path, status, latency, and request_id after the inner handler returns. Uses logger.Error for 5xx responses and logger.Info for all others.

CORS

mux.Use(httpmw.CORS([]string{"https://app.example.com", "https://admin.example.com"}))

Sets Access-Control-Allow-Origin, Access-Control-Allow-Methods, and Access-Control-Allow-Headers for matching origins. OPTIONS requests are short-circuited with 204 No Content.

Allowed methods: GET, HEAD, PUT, PATCH, POST, DELETE, OPTIONS Allowed headers: Content-Type, Authorization, X-Request-ID

Logger interface

RequestLogger accepts any value satisfying the Logger interface — satisfied by logz.Logger via duck typing:

type Logger interface {
    Info(msg string, args ...any)
    Error(msg string, err error, args ...any)
    With(args ...any) Logger
}

StatusRecorder

StatusRecorder is exported for use in custom middleware that needs to inspect the written status code:

rec := &httpmw.StatusRecorder{ResponseWriter: w, Status: http.StatusOK}
next.ServeHTTP(rec, r)
fmt.Println(rec.Status) // e.g. 404

Dependencies

  • code.nochebuena.dev/go/logz
Description
HTTP middleware toolkit: request ID, recovery, CORS, and structured request logging.
Readme MIT 48 KiB
2026-03-18 18:05:57 -06:00
Languages
Go 100%