From 939c733ace6af4956698633f4fddf08647d439d5 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Tue, 13 Jan 2026 03:03:34 -0700 Subject: [PATCH] wip: add more middleware examples --- http/middleware/README.md | 26 +++++++++++++++++++++++++- http/middleware/basicauth.go | 30 ++++++++++++++++++++++++++++++ http/middleware/middleware.go | 5 +++-- 3 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 http/middleware/basicauth.go diff --git a/http/middleware/README.md b/http/middleware/README.md index e2d8ca2..f6a7f67 100644 --- a/http/middleware/README.md +++ b/http/middleware/README.md @@ -89,6 +89,27 @@ func recoverPanics(next http.Handler) http.Handler { } ``` +#### Example: Panic handler + +```go +func RecoverPanics(next http.HandlerFunc) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + defer func() { + if _err := recover(); _err != nil { + err, ok := _err.(error) + if !ok { + err = fmt.Errorf("%v", _err) + } + api.InternalError(w, r, err) + return + } + }() + + next.ServeHTTP(w, r) + } +} +``` + #### Example: Request logger ```go @@ -121,7 +142,10 @@ func basicAuth(next http.Handler) http.Handler { return } - next.ServeHTTP(w, r) + ctx := r.Context() + ctx = context.WithValue(ctx, UsernameKey, username) + next.ServeHTTP(w, r.WithContext(ctx)) + // or just next.ServeHTTP(w, r) } } ``` diff --git a/http/middleware/basicauth.go b/http/middleware/basicauth.go new file mode 100644 index 0000000..306b646 --- /dev/null +++ b/http/middleware/basicauth.go @@ -0,0 +1,30 @@ +package middleware + +import ( + "context" + "net/http" +) + +type BasicAuthVerifier interface { + Verify(string, string) bool +} + +type usernameKeyType struct{} + +var UsernameKey usernameKeyType + +func BasicAuth(v BasicAuthVerifier) func(http.HandlerFunc) http.HandlerFunc { + return func(next http.HandlerFunc) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + username, password, ok := r.BasicAuth() + if !ok || !v.Verify(username, password) { + // s.jsonError(w, http.StatusUnauthorized, "unauthorized", "Unauthorized", "Invalid credentials") + return + } + + ctx := r.Context() + ctx = context.WithValue(ctx, UsernameKey, username) + next.ServeHTTP(w, r.WithContext(ctx)) + } + } +} diff --git a/http/middleware/middleware.go b/http/middleware/middleware.go index 51c39ce..7f3e2bd 100644 --- a/http/middleware/middleware.go +++ b/http/middleware/middleware.go @@ -12,6 +12,7 @@ package middleware import ( + "errors" "net/http" "slices" ) @@ -33,7 +34,7 @@ type MiddlewareChain struct { // Handle composes middleware with the final handler func (c MiddlewareChain) Handle(handler http.Handler) http.Handler { if handler == nil { - panic("mw.New(...).Use(...).Handle(-->this<--) requires a handler") + panic(errors.New("mw.New(...).Use(...).Handle(-->this<--) requires a handler")) } middlewares := make([]Middleware, len(c.middlewares)) @@ -86,7 +87,7 @@ func (c MiddlewareMux) HandleFunc(path string, handler http.HandlerFunc) { // Handle composes middleware with the final handler func (c MiddlewareMux) handle(handler http.Handler) http.Handler { if handler == nil { - panic("mw.New(...).Use(...).Handle(-->this<--) requires a handler") + panic(errors.New("mw.New(...).Use(...).Handle(-->this<--) requires a handler")) } middlewares := make([]Middleware, len(c.middlewares))