Files
homelab-frontend/internal/server/router.go
T

85 lines
2.5 KiB
Go
Raw Normal View History

2026-08-19 20:52:13 -07:00
package server
import (
"net/http"
"strings"
"forgejo.riotpiao.com/rock/homelab-frontend/internal/serviceadapter"
2026-08-19 20:52:13 -07:00
)
// Router implements an HTTP handler that routes health endpoints,
// ServiceAdapter X-Service requests, Temporal workflow endpoints,
// S3/SigV4 endpoints, and other requests to upstream handlers.
2026-08-19 20:52:13 -07:00
type Router struct {
healthChecker *HealthChecker
dispatcher *serviceadapter.Dispatcher
temporalHandler http.Handler
s3Handler http.Handler // S3/SigV4 proxy
2026-08-19 20:52:13 -07:00
upstreamHandler http.Handler
}
// NewRouter creates a new router with health endpoints.
// Health endpoints (/healthz and /readyz) are handled locally.
// X-Service requests are dispatched via ServiceAdapter CRD.
// Temporal endpoints (/workflow*) are routed to temporalHandler.
// S3 endpoints (/v1/s3/*) are routed to s3Handler.
2026-08-19 20:52:13 -07:00
// All other paths are passed to the upstream handler.
func NewRouter(healthChecker *HealthChecker, dispatcher *serviceadapter.Dispatcher, temporalHandler http.Handler, s3Handler http.Handler, upstreamHandler http.Handler) *Router {
2026-08-19 20:52:13 -07:00
return &Router{
healthChecker: healthChecker,
dispatcher: dispatcher,
temporalHandler: temporalHandler,
s3Handler: s3Handler,
2026-08-19 20:52:13 -07:00
upstreamHandler: upstreamHandler,
}
}
// ServeHTTP implements http.Handler.
// Priority order:
// 1. /healthz and /readyz to health handlers
// 2. X-Service header to ServiceAdapter dispatcher (phase 8)
// 3. /workflow* to temporal handler
// 4. /v1/s3/* to S3/SigV4 handler
// 5. All other paths to upstream handler (phase 0-7)
2026-08-19 20:52:13 -07:00
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// Health endpoints first
switch req.URL.Path {
case "/healthz":
2026-08-19 20:52:13 -07:00
LivenessHandler(r.healthChecker)(w, req)
return
case "/readyz":
2026-08-19 20:52:13 -07:00
ReadinessHandler(r.healthChecker)(w, req)
return
2026-08-19 20:52:13 -07:00
}
// X-Service (ServiceAdapter) routing - checked before path-based routing
if req.Header.Get("X-Service") != "" {
if r.dispatcher != nil {
r.dispatcher.Dispatch(w, req)
return
}
}
// Workflow endpoints
switch req.URL.Path {
case "/workflow", "/workflow/health", "/workflow/metrics":
r.temporalHandler.ServeHTTP(w, req)
return
}
// S3/SigV4 proxy endpoints
if req.URL.Path != "" && req.URL.Path[0] == '/' && len(req.URL.Path) > 1 {
// Check for /v1/s3/* pattern
parts := strings.Split(strings.TrimPrefix(req.URL.Path, "/"), "/")
if len(parts) >= 3 && parts[0] == "v1" && parts[1] == "s3" {
if r.s3Handler != nil {
r.s3Handler.ServeHTTP(w, req)
return
}
}
}
// Default: upstream handler (all other paths)
r.upstreamHandler.ServeHTTP(w, req)
2026-08-19 20:52:13 -07:00
}