// Package api provides HTTP handlers and middleware for the Silo API. package api import ( "net/http" "time" "github.com/go-chi/chi/v5/middleware" "github.com/rs/zerolog" ) // RequestLogger returns a middleware that logs HTTP requests using zerolog. func RequestLogger(logger zerolog.Logger) func(next http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { start := time.Now() ww := middleware.NewWrapResponseWriter(w, r.ProtoMajor) defer func() { logger.Info(). Str("method", r.Method). Str("path", r.URL.Path). Str("query", r.URL.RawQuery). Int("status", ww.Status()). Int("bytes", ww.BytesWritten()). Dur("duration", time.Since(start)). Str("remote", r.RemoteAddr). Str("user_agent", r.UserAgent()). Msg("request") }() next.ServeHTTP(ww, r) }) } } // Recoverer returns a middleware that recovers from panics and logs them. func Recoverer(logger zerolog.Logger) func(next http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { defer func() { if rec := recover(); rec != nil { logger.Error(). Interface("panic", rec). Str("method", r.Method). Str("path", r.URL.Path). Msg("panic recovered") http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) } }() next.ServeHTTP(w, r) }) } }