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]>
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
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"}`))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user