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"` }