You've already forked agentic-coding-workflow
58 lines
1.8 KiB
Go
58 lines
1.8 KiB
Go
package httpx
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
)
|
|
|
|
// RouterDeps bundles the dependencies needed to assemble the router.
|
|
// MVP exposes only liveness/readiness probe hooks; later phases (auth
|
|
// resolver, module handlers, etc.) will add fields here rather than
|
|
// growing NewRouter's signature.
|
|
type RouterDeps struct {
|
|
// HealthCheck is invoked from GET /healthz. Returning a non-nil
|
|
// error renders 503 with the error message as the body. If nil,
|
|
// /healthz unconditionally returns 200 "ok".
|
|
HealthCheck func(*http.Request) error
|
|
// ReadyCheck is invoked from GET /readyz with the same contract.
|
|
ReadyCheck func(*http.Request) error
|
|
// SPAHandler 为 nil 时禁用前端 fallback;非 nil 时挂到 chi NotFound,
|
|
// 把未匹配的请求交给 SPA handler 处理(静态文件 + index.html 回退)。
|
|
SPAHandler http.Handler
|
|
}
|
|
|
|
// NewRouter builds the application's chi.Router with the standard
|
|
// liveness/readiness endpoints attached. The return type is the
|
|
// chi.Router interface (not *chi.Mux) so call sites depend only on
|
|
// behaviour shared with future routing layers.
|
|
func NewRouter(deps RouterDeps) chi.Router {
|
|
r := chi.NewRouter()
|
|
|
|
r.Get("/healthz", func(w http.ResponseWriter, req *http.Request) {
|
|
if deps.HealthCheck != nil {
|
|
if err := deps.HealthCheck(req); err != nil {
|
|
http.Error(w, err.Error(), http.StatusServiceUnavailable)
|
|
return
|
|
}
|
|
}
|
|
_, _ = w.Write([]byte("ok"))
|
|
})
|
|
|
|
r.Get("/readyz", func(w http.ResponseWriter, req *http.Request) {
|
|
if deps.ReadyCheck != nil {
|
|
if err := deps.ReadyCheck(req); err != nil {
|
|
http.Error(w, err.Error(), http.StatusServiceUnavailable)
|
|
return
|
|
}
|
|
}
|
|
_, _ = w.Write([]byte("ok"))
|
|
})
|
|
|
|
if deps.SPAHandler != nil {
|
|
r.NotFound(deps.SPAHandler.ServeHTTP)
|
|
}
|
|
|
|
return r
|
|
}
|