50 lines
1.0 KiB
Go
50 lines
1.0 KiB
Go
package middleware
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/hex"
|
|
"log/slog"
|
|
"net/http"
|
|
"time"
|
|
|
|
applog "github.com/noderunners/nip05api/internal/log"
|
|
)
|
|
|
|
type statusRecorder struct {
|
|
http.ResponseWriter
|
|
status int
|
|
}
|
|
|
|
func (s *statusRecorder) WriteHeader(code int) {
|
|
s.status = code
|
|
s.ResponseWriter.WriteHeader(code)
|
|
}
|
|
|
|
func newRequestID() string {
|
|
b := make([]byte, 8)
|
|
_, _ = rand.Read(b)
|
|
return hex.EncodeToString(b)
|
|
}
|
|
|
|
func Logging(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
id := r.Header.Get("X-Request-ID")
|
|
if id == "" {
|
|
id = newRequestID()
|
|
}
|
|
w.Header().Set("X-Request-ID", id)
|
|
ctx := applog.WithRequestID(r.Context(), id)
|
|
rec := &statusRecorder{ResponseWriter: w, status: 200}
|
|
start := time.Now()
|
|
next.ServeHTTP(rec, r.WithContext(ctx))
|
|
slog.Info("http",
|
|
"request_id", id,
|
|
"method", r.Method,
|
|
"path", r.URL.Path,
|
|
"status", rec.status,
|
|
"duration_ms", time.Since(start).Milliseconds(),
|
|
"remote", r.RemoteAddr,
|
|
)
|
|
})
|
|
}
|