extract middlewares to lightmux-contrib
Removes pkg/middleware. The Logger, Recoverer, and RealIP middlewares now live in the sibling lightmux-contrib module as the realip, requestlog, and recoverer packages, each exposing a single New(...) constructor. The Middleware type alias moves to pkg/router. The splinter dependency is dropped from go.mod; only errx remains. BREAKING CHANGE: consumers must replace pkg/middleware imports with the corresponding lightmux-contrib sub-packages. See README for the new usage. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d983cca25e
commit
22277186ae
15 changed files with 44 additions and 612 deletions
33
README.md
33
README.md
|
|
@ -22,12 +22,10 @@ import (
|
|||
"strconv"
|
||||
|
||||
"git.juancwu.dev/juancwu/lightmux"
|
||||
"git.juancwu.dev/juancwu/lightmux/pkg/middleware"
|
||||
)
|
||||
|
||||
func main() {
|
||||
mux := lightmux.New()
|
||||
mux.Use(middleware.Recoverer, middleware.Logger)
|
||||
|
||||
mux.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintln(w, "hello from lightmux")
|
||||
|
|
@ -71,34 +69,29 @@ There are two ways to attach middleware: chain-style with `Use`, or per-route as
|
|||
|
||||
```go
|
||||
mux := lightmux.New()
|
||||
mux.Use(middleware.Recoverer, middleware.Logger) // applies to every route registered after
|
||||
mux.Use(authMiddleware) // applies to every route registered after
|
||||
|
||||
mux.Get("/admin", adminHandler, requireAdmin) // requireAdmin only on this route
|
||||
mux.Get("/admin", adminHandler, requireAdmin) // requireAdmin only on this route
|
||||
```
|
||||
|
||||
Order is outer → inner: `Use`-order first, then per-route mws. The outermost middleware runs first on the request and last on the response.
|
||||
|
||||
Middleware values are plain `func(http.Handler) http.Handler`, so any stdlib-compatible middleware works without an adapter.
|
||||
|
||||
## Built-in middleware
|
||||
An opinionated set of middlewares (request logging, panic recovery, real-IP resolution) lives in a sibling module — see [lightmux-contrib](https://git.juancwu.dev/juancwu/lightmux-contrib):
|
||||
|
||||
The `pkg/middleware` package ships:
|
||||
|
||||
- **`Logger`** — emits a structured `http.request` record (method, path, status, duration, client) via [splinter](https://git.juancwu.dev/juancwu/splinter)'s default logger. The `client` field is `r.RemoteAddr`, so pairing with `RealIP` makes it the resolved client IP.
|
||||
- **`LoggerWith(*splinter.Logger)`** — same, but routes records through the supplied splinter logger instead of the default.
|
||||
- **`Recoverer`** — catches panics inside handlers, wraps the value with [errx](https://git.juancwu.dev/juancwu/errx) under op `middleware.Recoverer`, logs it with the stack, and writes a 500 response.
|
||||
- **`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). Always trusts these headers — only register it when the service sits behind a trusted proxy.
|
||||
- **`RealIPWith(trusted ...netip.Prefix)`** — same, but only honors the headers when the immediate peer's IP falls within one of the trusted prefixes. Requests from outside the allowlist pass through untouched.
|
||||
|
||||
```go
|
||||
custom := splinter.New(splinter.WithStream(...))
|
||||
mux.Use(middleware.Recoverer, middleware.LoggerWith(custom))
|
||||
```sh
|
||||
go get git.juancwu.dev/juancwu/lightmux-contrib
|
||||
```
|
||||
|
||||
When using `RealIP` together with `Logger`, register `RealIP` first so the logged `client` field is the resolved client IP rather than the proxy's peer address:
|
||||
|
||||
```go
|
||||
mux.Use(middleware.RealIP, middleware.Logger)
|
||||
import (
|
||||
"git.juancwu.dev/juancwu/lightmux-contrib/realip"
|
||||
"git.juancwu.dev/juancwu/lightmux-contrib/recoverer"
|
||||
"git.juancwu.dev/juancwu/lightmux-contrib/requestlog"
|
||||
)
|
||||
|
||||
mux.Use(recoverer.New(), realip.New(), requestlog.New(nil))
|
||||
```
|
||||
|
||||
## Path parameters
|
||||
|
|
@ -114,5 +107,5 @@ mux.Get("/items/{name}", func(w http.ResponseWriter, r *http.Request) {
|
|||
## Notes
|
||||
|
||||
- `mux.Get("/", h)` registers `"GET /"`, which is a stdlib **subtree** pattern — it matches every unmatched path. Use `"/{$}"` to match only the literal root.
|
||||
- Bad route registrations (invalid prefix, conflicting wildcards) panic at startup, matching stdlib `http.ServeMux` behavior. `Recoverer` handles panics that occur *inside* request handlers.
|
||||
- Bad route registrations (invalid prefix, conflicting wildcards) panic at startup, matching stdlib `http.ServeMux` behavior. The `recoverer` middleware in [lightmux-contrib](https://git.juancwu.dev/juancwu/lightmux-contrib) handles panics that occur *inside* request handlers.
|
||||
- Group prefixes apply to the path only — they never inject a host. Routes can still carry an explicit host via `Handle("GET host.com/path", h)`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue