package http import ( "log/slog" "net/http" "time" ) type middlewareFunc func(http.Handler) http.Handler func middlewarePanicRecovery(log *slog.Logger) middlewareFunc { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { defer func() { rec := recover() if rec == nil { return } log.ErrorContext( r.Context(), "panic acquired during request", slog.Any("panic", rec), ) }() next.ServeHTTP(w, r) }) } } func middlewareLogger(log *slog.Logger) middlewareFunc { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { start := time.Now() requestID := r.Header.Get("x-request-id") if requestID == "" { requestID = randomID() } w.Header().Set("x-request-id", requestID) method := r.Method path := r.URL.Path query := r.URL.Query().Encode() log.DebugContext( r.Context(), "request processing", slog.String("request_id", requestID), slog.String("method", method), slog.String("path", path), slog.String("query", query), ) next.ServeHTTP(w, r) log.InfoContext( r.Context(), "request finished", slog.Int64("elapsed", time.Since(start).Milliseconds()), ) }) } } func multipleMiddlewares(mws ...middlewareFunc) middlewareFunc { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { for _, mw := range mws { next = mw(next) } next.ServeHTTP(w, r) }) } }