delete runable example and update readme
This commit is contained in:
parent
f46916fdf5
commit
24d8590b56
2 changed files with 108 additions and 47 deletions
109
README.md
109
README.md
|
|
@ -1,3 +1,110 @@
|
|||
# lightmux
|
||||
|
||||
Simple router/mux for Go projects.
|
||||
A small, idiomatic wrapper around Go 1.22+ `net/http.ServeMux` that adds method-named convenience methods, composable groups, and per-route middleware — without abandoning the stdlib pattern syntax.
|
||||
|
||||
## Installation
|
||||
|
||||
Requires Go 1.22 or later (uses `http.ServeMux`'s method+pattern syntax and `r.PathValue`).
|
||||
|
||||
```sh
|
||||
go get git.juancwu.dev/juancwu/lightmux
|
||||
```
|
||||
|
||||
## Quick start
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"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")
|
||||
})
|
||||
|
||||
mux.Get("/users/{id}", func(w http.ResponseWriter, r *http.Request) {
|
||||
id, err := strconv.Atoi(r.PathValue("id"))
|
||||
if err != nil {
|
||||
http.Error(w, "bad id", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
fmt.Fprintf(w, "user %d\n", id)
|
||||
})
|
||||
|
||||
api := mux.Group("/api")
|
||||
api.Get("/ping", func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintln(w, "pong")
|
||||
})
|
||||
|
||||
log.Fatal(http.ListenAndServe(":8080", mux))
|
||||
}
|
||||
```
|
||||
|
||||
## Groups
|
||||
|
||||
`Group` returns a sub-mux that shares the underlying ServeMux but carries its own prefix and middleware stack. Groups can be nested.
|
||||
|
||||
```go
|
||||
api := mux.Group("/api", authMiddleware)
|
||||
api.Get("/users/{id}", getUser)
|
||||
|
||||
v1 := api.Group("/v1")
|
||||
v1.Get("/ping", pong) // registered as "GET /api/v1/ping"
|
||||
```
|
||||
|
||||
Middleware is snapshotted into the child at `Group()` time. Calling `parent.Use(mw)` *after* a `Group()` does not retroactively wrap the child's routes — register middleware before creating groups, or pass it to `Group(prefix, mw...)` explicitly.
|
||||
|
||||
## Middleware
|
||||
|
||||
There are two ways to attach middleware: chain-style with `Use`, or per-route as a variadic tail.
|
||||
|
||||
```go
|
||||
mux := lightmux.New()
|
||||
mux.Use(middleware.Recoverer, middleware.Logger) // applies to every route registered after
|
||||
|
||||
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
|
||||
|
||||
The `pkg/middleware` package ships:
|
||||
|
||||
- **`Logger`** — emits a structured `http.request` record (method, path, status, duration) via [splinter](https://git.juancwu.dev/juancwu/splinter)'s default logger.
|
||||
- **`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.
|
||||
|
||||
```go
|
||||
custom := splinter.New(splinter.WithStream(...))
|
||||
mux.Use(middleware.Recoverer, middleware.LoggerWith(custom))
|
||||
```
|
||||
|
||||
## Path parameters
|
||||
|
||||
lightmux is a thin wrapper, so path parameters work the stdlib way:
|
||||
|
||||
```go
|
||||
mux.Get("/items/{name}", func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintln(w, r.PathValue("name"))
|
||||
})
|
||||
```
|
||||
|
||||
## 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.
|
||||
- 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