Files
httpx/server/health.go
Aleksey Shakhmatov cea75d198b 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>
2026-03-21 13:41:54 +03:00

56 lines
1.4 KiB
Go

package server
import (
"encoding/json"
"net/http"
)
// ReadinessChecker is a function that reports whether a dependency is ready.
// Return nil if healthy, or an error describing the problem.
type ReadinessChecker func() error
// HealthHandler returns an http.Handler that exposes liveness and readiness
// endpoints:
//
// - GET /healthz — liveness check, always returns 200 OK
// - GET /readyz — readiness check, returns 200 if all checkers pass, 503 otherwise
func HealthHandler(checkers ...ReadinessChecker) http.Handler {
mux := http.NewServeMux()
mux.HandleFunc("GET /healthz", func(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
_ = json.NewEncoder(w).Encode(healthResponse{Status: "ok"})
})
mux.HandleFunc("GET /readyz", func(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "application/json")
var errs []string
for _, check := range checkers {
if err := check(); err != nil {
errs = append(errs, err.Error())
}
}
if len(errs) > 0 {
w.WriteHeader(http.StatusServiceUnavailable)
_ = json.NewEncoder(w).Encode(healthResponse{
Status: "unavailable",
Errors: errs,
})
return
}
w.WriteHeader(http.StatusOK)
_ = json.NewEncoder(w).Encode(healthResponse{Status: "ok"})
})
return mux
}
type healthResponse struct {
Status string `json:"status"`
Errors []string `json:"errors,omitempty"`
}