Files
homelab-frontend/internal/server/health.go
T
Story Crater BotandClaude Opus 5 058f11cf2b
CI / Test (push) Canceled after 0s
CI / Vet (push) Canceled after 0s
CI / Build (push) Canceled after 0s
CI / Security (govulncheck) (push) Canceled after 0s
chore: initial commit of Go API gateway
Baseline for the Kong replacement on api.riotpiao.com. Brings the working
tree under version control for the first time: gateway source, the task
board that drives the agent runs, test fixtures, and K8s manifests.

Anchor the gateway ignore rule to the repo root. Unanchored, "gateway"
also matched the cmd/gateway/ source directory, so the program entrypoint
was excluded from every commit.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2026-08-19 20:54:34 -07:00

91 lines
2.4 KiB
Go

package server
import (
"net/http"
"sync"
)
// HealthChecker provides health and readiness check information.
type HealthChecker struct {
mu sync.RWMutex
configValid bool
jwksHasFetched bool
authEnabled bool
}
// NewHealthChecker creates a new health checker instance.
func NewHealthChecker(configValid bool, authEnabled bool) *HealthChecker {
return &HealthChecker{
configValid: configValid,
jwksHasFetched: false,
authEnabled: authEnabled,
}
}
// MarkJWKSFetched marks that JWKS has been fetched successfully.
func (hc *HealthChecker) MarkJWKSFetched() {
hc.mu.Lock()
defer hc.mu.Unlock()
hc.jwksHasFetched = true
}
// IsReady checks if the server is ready to serve traffic.
// It returns true if:
// - Configuration is valid
// - If auth is enabled, JWKS has been fetched at least once
func (hc *HealthChecker) IsReady() bool {
hc.mu.RLock()
defer hc.mu.RUnlock()
if !hc.configValid {
return false
}
// If auth is enabled, we must have fetched JWKS at least once
if hc.authEnabled && !hc.jwksHasFetched {
return false
}
return true
}
// IsAlive returns true if the process is running.
// This is always true since if it weren't, we wouldn't be running this code.
func (hc *HealthChecker) IsAlive() bool {
return true
}
// LivenessHandler returns a handler for the /healthz endpoint.
// It returns 200 whenever the process is alive.
// It performs no network I/O.
func LivenessHandler(hc *HealthChecker) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if !hc.IsAlive() {
w.WriteHeader(http.StatusServiceUnavailable)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write([]byte(`{"status":"alive"}`))
}
}
// ReadinessHandler returns a handler for the /readyz endpoint.
// It returns 200 only when configuration is valid and, if auth is enabled,
// JWKS has been fetched at least once.
// It returns non-2xx status while configuration is invalid or JWKS has never
// been fetched.
func ReadinessHandler(hc *HealthChecker) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if !hc.IsReady() {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusServiceUnavailable)
w.Write([]byte(`{"status":"not_ready"}`))
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write([]byte(`{"status":"ready"}`))
}
}