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>
57 lines
1.7 KiB
Go
57 lines
1.7 KiB
Go
package server
|
|
|
|
import "net/http"
|
|
|
|
// Middleware wraps an http.Handler to add behavior.
|
|
// This is the server-side counterpart of the client middleware type
|
|
// func(http.RoundTripper) http.RoundTripper.
|
|
type Middleware func(http.Handler) http.Handler
|
|
|
|
// Chain composes middlewares so that Chain(A, B, C)(handler) == A(B(C(handler))).
|
|
// Middlewares are applied from right to left: C wraps handler first, then B wraps
|
|
// the result, then A wraps last. This means A is the outermost layer and sees
|
|
// every request first.
|
|
func Chain(mws ...Middleware) Middleware {
|
|
return func(h http.Handler) http.Handler {
|
|
for i := len(mws) - 1; i >= 0; i-- {
|
|
h = mws[i](h)
|
|
}
|
|
return h
|
|
}
|
|
}
|
|
|
|
// statusWriter wraps http.ResponseWriter to capture the response status code.
|
|
// It implements Unwrap() so that http.ResponseController can access the
|
|
// underlying ResponseWriter's optional interfaces (Flusher, Hijacker, etc.).
|
|
type statusWriter struct {
|
|
http.ResponseWriter
|
|
status int
|
|
written bool
|
|
}
|
|
|
|
// WriteHeader captures the status code and delegates to the underlying writer.
|
|
func (w *statusWriter) WriteHeader(code int) {
|
|
if !w.written {
|
|
w.status = code
|
|
w.written = true
|
|
}
|
|
w.ResponseWriter.WriteHeader(code)
|
|
}
|
|
|
|
// Write delegates to the underlying writer, defaulting status to 200 if
|
|
// WriteHeader was not called explicitly.
|
|
func (w *statusWriter) Write(b []byte) (int, error) {
|
|
if !w.written {
|
|
w.status = http.StatusOK
|
|
w.written = true
|
|
}
|
|
return w.ResponseWriter.Write(b)
|
|
}
|
|
|
|
// Unwrap returns the underlying ResponseWriter. This is required for
|
|
// http.ResponseController to detect optional interfaces like http.Flusher
|
|
// and http.Hijacker on the original writer.
|
|
func (w *statusWriter) Unwrap() http.ResponseWriter {
|
|
return w.ResponseWriter
|
|
}
|