Composable HTTP Middleware Chain
Compose HTTP handlers through middleware that wrap the next handler, adding logging, recovery, and request identifiers without duplication.
Code
package main
import (
"log"
"net/http"
"time"
)
type Middleware func(http.Handler) http.Handler
func chain(h http.Handler, middleware ...Middleware) http.Handler {
for i := len(middleware) - 1; i >= 0; i-- {
h = middleware[i](h)
}
return h
}
func logging(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
next.ServeHTTP(w, r)
log.Printf("method=%s path=%s duration=%s", r.Method, r.URL.Path, time.Since(start))
})
}
func recoverPanic(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func() {
if rec := recover(); rec != nil {
http.Error(w, "internal error", http.StatusInternalServerError)
}
}()
next.ServeHTTP(w, r)
})
}Report a problem with this exampleOpens a pre-filled issue on GitHub.