diff --git a/cmd/gateway/main.go b/cmd/gateway/main.go index 1fd8caa..7a8ae3a 100644 --- a/cmd/gateway/main.go +++ b/cmd/gateway/main.go @@ -12,6 +12,7 @@ import ( "forgejo.riotpiao.com/rock/homelab-frontend/internal/config" "forgejo.riotpiao.com/rock/homelab-frontend/internal/proxy" "forgejo.riotpiao.com/rock/homelab-frontend/internal/server" + "forgejo.riotpiao.com/rock/homelab-frontend/internal/serviceadapter" "forgejo.riotpiao.com/rock/homelab-frontend/internal/temporal" ) @@ -51,8 +52,13 @@ func main() { healthChecker := server.NewHealthChecker(true, authEnabled) srv.SetHealthChecker(healthChecker) - // Create router that handles health endpoints, temporal endpoints, and passes others to upstream - router := server.NewRouter(healthChecker, temporalHandler, upstreamHandler) + // Create ServiceAdapter registry and dispatcher (phase 8) + registry := serviceadapter.NewRegistry(nil) // nil uses default logger + dispatcher := serviceadapter.NewDispatcher(registry) + + // Create router that handles health endpoints, X-Service (ServiceAdapter) routing, + // temporal endpoints, and passes others to upstream handler + router := server.NewRouter(healthChecker, dispatcher, temporalHandler, upstreamHandler) srv.SetHandler(router) // Set up signal handling diff --git a/internal/server/router.go b/internal/server/router.go index 63dc8de..cc69ace 100644 --- a/internal/server/router.go +++ b/internal/server/router.go @@ -2,42 +2,66 @@ package server import ( "net/http" + + "forgejo.riotpiao.com/rock/homelab-frontend/internal/serviceadapter" ) // Router implements an HTTP handler that routes health endpoints, -// Temporal workflow endpoints, and other requests to upstream handlers. +// ServiceAdapter X-Service requests, Temporal workflow endpoints, +// and other requests to upstream handlers. type Router struct { healthChecker *HealthChecker + dispatcher *serviceadapter.Dispatcher temporalHandler http.Handler 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. // All other paths are passed to the upstream handler. -func NewRouter(healthChecker *HealthChecker, temporalHandler http.Handler, upstreamHandler http.Handler) *Router { +func NewRouter(healthChecker *HealthChecker, dispatcher *serviceadapter.Dispatcher, temporalHandler http.Handler, upstreamHandler http.Handler) *Router { return &Router{ healthChecker: healthChecker, + dispatcher: dispatcher, temporalHandler: temporalHandler, upstreamHandler: upstreamHandler, } } // ServeHTTP implements http.Handler. -// It routes /healthz and /readyz to health handlers, -// /workflow* to the temporal handler, -// and passes all other paths to the upstream 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. All other paths to upstream handler (phase 0-7) func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) { - switch { - case req.URL.Path == "/healthz": + // Health endpoints first + switch req.URL.Path { + case "/healthz": LivenessHandler(r.healthChecker)(w, req) - case req.URL.Path == "/readyz": + return + case "/readyz": ReadinessHandler(r.healthChecker)(w, req) - case req.URL.Path == "/workflow" || req.URL.Path == "/workflow/health" || req.URL.Path == "/workflow/metrics": - // Route all /workflow endpoints to temporal handler - r.temporalHandler.ServeHTTP(w, req) - default: - r.upstreamHandler.ServeHTTP(w, req) + return } + + // 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 + } + + // Default: upstream handler (all other paths) + r.upstreamHandler.ServeHTTP(w, req) }