initial implementation

This commit is contained in:
juancwu 2026-04-25 20:26:07 +00:00
commit cb373e637b
16 changed files with 777 additions and 1 deletions

87
pkg/router/mux.go Normal file
View file

@ -0,0 +1,87 @@
// Package router provides a thin, idiomatic wrapper around the Go 1.22+
// net/http ServeMux. It adds method-named convenience methods (Get, Post,
// ...), per-route and group middleware, and Group sub-routers that share the
// underlying mux while carrying their own prefix and middleware stack.
package router
import (
"net/http"
"git.juancwu.dev/juancwu/lightmux/pkg/middleware"
)
type Mux struct {
root *http.ServeMux
prefix string
middlewares []middleware.Middleware
}
func New() *Mux {
sm := http.NewServeMux()
return &Mux{root: sm}
}
func (m *Mux) Use(mws ...middleware.Middleware) {
m.middlewares = append(m.middlewares, mws...)
}
// Group returns a child Mux that registers on the same underlying ServeMux but
// with its prefix appended and the parent's current middlewares snapshotted.
// Use() calls made on the parent after Group() do not propagate to the child.
func (m *Mux) Group(prefix string, mws ...middleware.Middleware) *Mux {
validateGroupPrefix(prefix)
mwsCopy := make([]middleware.Middleware, 0, len(m.middlewares)+len(mws))
mwsCopy = append(mwsCopy, m.middlewares...)
mwsCopy = append(mwsCopy, mws...)
return &Mux{
root: m.root,
prefix: m.prefix + normalizeGroupPrefix(prefix),
middlewares: mwsCopy,
}
}
func (m *Mux) Handle(pattern string, h http.Handler, mws ...middleware.Middleware) {
full := buildPattern("", m.prefix, pattern)
m.root.Handle(full, chain(h, m.middlewares, mws))
}
func (m *Mux) HandleFunc(pattern string, fn http.HandlerFunc, mws ...middleware.Middleware) {
m.Handle(pattern, fn, mws...)
}
func (m *Mux) method(method, path string, fn http.HandlerFunc, mws []middleware.Middleware) {
full := buildPattern(method, m.prefix, path)
m.root.Handle(full, chain(fn, m.middlewares, mws))
}
func (m *Mux) Get(path string, fn http.HandlerFunc, mws ...middleware.Middleware) {
m.method(http.MethodGet, path, fn, mws)
}
func (m *Mux) Post(path string, fn http.HandlerFunc, mws ...middleware.Middleware) {
m.method(http.MethodPost, path, fn, mws)
}
func (m *Mux) Put(path string, fn http.HandlerFunc, mws ...middleware.Middleware) {
m.method(http.MethodPut, path, fn, mws)
}
func (m *Mux) Patch(path string, fn http.HandlerFunc, mws ...middleware.Middleware) {
m.method(http.MethodPatch, path, fn, mws)
}
func (m *Mux) Delete(path string, fn http.HandlerFunc, mws ...middleware.Middleware) {
m.method(http.MethodDelete, path, fn, mws)
}
func (m *Mux) Options(path string, fn http.HandlerFunc, mws ...middleware.Middleware) {
m.method(http.MethodOptions, path, fn, mws)
}
func (m *Mux) Head(path string, fn http.HandlerFunc, mws ...middleware.Middleware) {
m.method(http.MethodHead, path, fn, mws)
}
func (m *Mux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
m.root.ServeHTTP(w, r)
}