add realip, requestlog, recoverer middlewares
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>
This commit is contained in:
parent
9dc0fc5d26
commit
b26ef7439e
10 changed files with 624 additions and 0 deletions
49
README.md
49
README.md
|
|
@ -1,2 +1,51 @@
|
|||
# lightmux-contrib
|
||||
|
||||
Opinionated middleware collection for [lightmux](https://git.juancwu.dev/juancwu/lightmux). Each middleware lives in its own sub-package so consumers only pull in the dependencies they actually use.
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
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).
|
||||
|
||||
```go
|
||||
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](https://git.juancwu.dev/juancwu/splinter).
|
||||
|
||||
```go
|
||||
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:
|
||||
|
||||
```go
|
||||
mux.Use(realip.New(), requestlog.New(nil))
|
||||
```
|
||||
|
||||
### `recoverer`
|
||||
|
||||
Catches panics inside handlers, wraps the value with [errx](https://git.juancwu.dev/juancwu/errx) under op `recoverer`, logs it with stack via the standard `log` package, and writes a 500 response.
|
||||
|
||||
```go
|
||||
import "git.juancwu.dev/juancwu/lightmux-contrib/recoverer"
|
||||
|
||||
mux.Use(recoverer.New())
|
||||
```
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue