Add production-ready HTTP server package with routing, health checks, and middleware
Introduces server/ sub-package as the server-side companion to the existing Client. Includes Router (over http.ServeMux with groups and mounting), graceful shutdown with signal handling, health endpoints (/healthz, /readyz), and built-in middlewares (RequestID, Recovery, Logging). Zero external dependencies. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
52
server/middleware_requestid.go
Normal file
52
server/middleware_requestid.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type requestIDKey struct{}
|
||||
|
||||
// RequestID returns a middleware that assigns a unique request ID to each
|
||||
// request. If the incoming request already has an X-Request-Id header, that
|
||||
// value is used. Otherwise a new UUID v4 is generated via crypto/rand.
|
||||
//
|
||||
// The request ID is stored in the request context (retrieve with
|
||||
// RequestIDFromContext) and set on the response X-Request-Id header.
|
||||
func RequestID() Middleware {
|
||||
return func(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 = newUUID()
|
||||
}
|
||||
|
||||
ctx := context.WithValue(r.Context(), requestIDKey{}, id)
|
||||
w.Header().Set("X-Request-Id", id)
|
||||
next.ServeHTTP(w, r.WithContext(ctx))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// RequestIDFromContext returns the request ID from the context, or an empty
|
||||
// string if none is set.
|
||||
func RequestIDFromContext(ctx context.Context) string {
|
||||
id, _ := ctx.Value(requestIDKey{}).(string)
|
||||
return id
|
||||
}
|
||||
|
||||
// newUUID generates a UUID v4 string using crypto/rand.
|
||||
func newUUID() string {
|
||||
var uuid [16]byte
|
||||
_, _ = rand.Read(uuid[:])
|
||||
|
||||
// Set version 4 (bits 12-15 of time_hi_and_version).
|
||||
uuid[6] = (uuid[6] & 0x0f) | 0x40
|
||||
// Set variant bits (10xx).
|
||||
uuid[8] = (uuid[8] & 0x3f) | 0x80
|
||||
|
||||
return fmt.Sprintf("%x-%x-%x-%x-%x",
|
||||
uuid[0:4], uuid[4:6], uuid[6:8], uuid[8:10], uuid[10:16])
|
||||
}
|
||||
Reference in New Issue
Block a user