Initial implementation of lightmux-contrib, a sibling module to lightmux that hosts opinionated middlewares with one sub-package per middleware: - realip: resolves the originating client IP from CF-Connecting-IP, True-Client-IP, X-Real-IP, or X-Forwarded-For. Optional peer-CIDR allowlist via netip.Prefix. - requestlog: emits a structured http.request record (method, path, status, duration, client) per request via splinter. - recoverer: catches panics, wraps with errx under op "recoverer", logs with stack, and writes a 500 response. Each package exposes a single New(...) constructor returning func(http.Handler) http.Handler. The contrib module intentionally does not import lightmux — middlewares interoperate via the standard stdlib middleware shape. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| realip | ||
| recoverer | ||
| requestlog | ||
| .gitignore | ||
| go.mod | ||
| go.sum | ||
| LICENSE | ||
| README.md | ||
| Taskfile.yml | ||
lightmux-contrib
Opinionated middleware collection for lightmux. Each middleware lives in its own sub-package so consumers only pull in the dependencies they actually use.
Installation
go get git.juancwu.dev/juancwu/lightmux-contrib
Packages
realip
Replaces r.RemoteAddr with the originating client IP from CF-Connecting-IP, True-Client-IP, X-Real-IP, or X-Forwarded-For (in that order).
import "git.juancwu.dev/juancwu/lightmux-contrib/realip"
mux.Use(realip.New()) // always trust headers
mux.Use(realip.New(netip.MustParsePrefix("10.0.0.0/8"))) // gated by peer CIDR
With no arguments, realip.New() always honors the proxy headers — only register it when the service sits behind a trusted proxy. With one or more netip.Prefix arguments, the headers are honored only when the immediate peer's IP falls within one of them.
requestlog
Emits a structured http.request record (method, path, status, duration, client) per request via splinter.
import "git.juancwu.dev/juancwu/lightmux-contrib/requestlog"
mux.Use(requestlog.New(nil)) // splinter.Default() resolved at request time
mux.Use(requestlog.New(custom)) // custom *splinter.Logger
When pairing with realip, register realip first so the client field is the resolved client IP rather than the proxy peer:
mux.Use(realip.New(), requestlog.New(nil))
recoverer
Catches panics inside handlers, wraps the value with errx under op recoverer, logs it with stack via the standard log package, and writes a 500 response.
import "git.juancwu.dev/juancwu/lightmux-contrib/recoverer"
mux.Use(recoverer.New())