Add standard middlewares: logging, headers, auth, and panic recovery
- Logging: structured slog output with method, URL, status, duration - DefaultHeaders/UserAgent: inject headers without overwriting existing - BearerAuth/BasicAuth: per-request token resolution and static credentials - Recovery: catches panics in the RoundTripper chain
This commit is contained in:
38
middleware/logging.go
Normal file
38
middleware/logging.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Logging returns a middleware that logs each request's method, URL, status
|
||||
// code, duration, and error (if any) using the provided structured logger.
|
||||
// Successful responses are logged at Info level; errors at Error level.
|
||||
func Logging(logger *slog.Logger) Middleware {
|
||||
return func(next http.RoundTripper) http.RoundTripper {
|
||||
return RoundTripperFunc(func(req *http.Request) (*http.Response, error) {
|
||||
start := time.Now()
|
||||
|
||||
resp, err := next.RoundTrip(req)
|
||||
|
||||
duration := time.Since(start)
|
||||
attrs := []slog.Attr{
|
||||
slog.String("method", req.Method),
|
||||
slog.String("url", req.URL.String()),
|
||||
slog.Duration("duration", duration),
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
attrs = append(attrs, slog.String("error", err.Error()))
|
||||
logger.LogAttrs(req.Context(), slog.LevelError, "request failed", attrs...)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
attrs = append(attrs, slog.Int("status", resp.StatusCode))
|
||||
logger.LogAttrs(req.Context(), slog.LevelInfo, "request completed", attrs...)
|
||||
|
||||
return resp, nil
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user