Files
atlas/internal/httpapp/middleware.go

47 lines
1.1 KiB
Go

package httpapp
import (
"context"
"crypto/rand"
"encoding/hex"
"log"
"net/http"
"time"
)
type ctxKey string
const requestIDKey ctxKey = "reqid"
func requestID(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 = newReqID()
}
w.Header().Set("X-Request-Id", id)
ctx := context.WithValue(r.Context(), requestIDKey, id)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
func logging(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
next.ServeHTTP(w, r)
d := time.Since(start)
id, _ := r.Context().Value(requestIDKey).(string)
log.Printf("%s %s %s rid=%s dur=%s", r.RemoteAddr, r.Method, r.URL.Path, id, d)
})
}
func newReqID() string {
var b [16]byte
if _, err := rand.Read(b[:]); err != nil {
// Fallback to timestamp-based ID if crypto/rand fails (extremely rare)
log.Printf("rand.Read failed, using fallback: %v", err)
return hex.EncodeToString([]byte(time.Now().Format(time.RFC3339Nano)))
}
return hex.EncodeToString(b[:])
}