labkit/v2/httpserver: Investigate and standardize HTTP router for LabKit v2 httpserver
## Context MR https://gitlab.com/gitlab-org/labkit/-/merge_requests/339 proposes a `v2/httpserver` package with an abstract `Router` interface backed by Go 1.22+ stdlib `net/http.ServeMux`. The interface is designed so the underlying router can be swapped without breaking consumers ([design requirements](https://gitlab.com/gitlab-org/quality/quality-engineering/team-tasks/-/issues/4283)). Before `v2/httpserver` lands, we need to decide which router to standardize on as the default for all GitLab Go services adopting LabKit v2. ## Problem Without a standard recommendation, each service will pick its own HTTP framework, fragmenting the ecosystem and complicating shared middleware, documentation, and onboarding. ## Evaluation attributes When comparing candidates, consider: - **stdlib compatibility**: Does it use native `http.Handler` / `http.HandlerFunc`? - **Middleware pattern**: Does it support `func(http.Handler) http.Handler` natively, or require adapters? - **Route grouping**: Can routes be grouped with shared middleware (e.g. auth group, API group)? - **Sub-routers / mounting**: Can independent route trees be composed (e.g. `Mount("/api", apiRouter)`)? - **Path parameter ergonomics**: How are URL parameters extracted and accessed? - **Dependency footprint**: Number and weight of transitive dependencies - **Maintenance posture**: Release cadence, response to CVEs, bus factor - **Ecosystem adoption**: Usage across the Go community, production references - **Migration cost**: Effort to adopt from the current stdlib default in the proposed `v2/httpserver` - **Performance**: Routing throughput for realistic workloads (not micro-benchmarks) ## Candidates ### Go stdlib `net/http.ServeMux` (Go 1.22+) The default in the proposed `v2/httpserver` ([!339](https://gitlab.com/gitlab-org/labkit/-/merge_requests/339)). Zero dependencies. Supports method-based routing and path parameters since Go 1.22. **Pros:** - Zero external dependencies - Maintained by the Go team, guaranteed long-term support - Native `http.Handler`, no adapters needed - No learning curve for Go developers **Cons:** - No route grouping or sub-router support (must be built manually) - No middleware chaining API - Nested `ServeMux` has [unexpected pattern matching behavior](https://github.com/golang/go/issues/72789) - Pattern conflicts cause panics rather than errors - LabKit would need to build grouping/chaining abstractions on top ### chi (`github.com/go-chi/chi/v5`) ~21,800 GitHub stars. 100% `http.Handler` compatible. Zero external dependencies. **Pros:** - Native `http.Handler` and `func(http.Handler) http.Handler` middleware - Built-in route grouping (`r.Group`, `r.Route`) and sub-routers (`r.Mount`) - Zero external dependencies, core router is <1000 LOC - Rich built-in middleware package (logger, recoverer, timeout, compress) - Battle-tested at Cloudflare, Heroku, 99Designs - Design philosophy (stdlib-first, composable) aligns with LabKit's goals **Cons:** - Release cadence has slowed (mature, but fewer releases) - Historical vulnerability in RedirectSlashes middleware (fixed in v5) - Third-party dependency (even if lightweight) ### httprouter (`github.com/julienschmidt/httprouter`) ~17,100 GitHub stars. Radix-tree based, extremely fast. **Pros:** - Very fast routing performance - Zero dependencies **Cons:** - Custom handler signature: `func(w, r, httprouter.Params)`, not `http.Handler` - No middleware support, no route grouping, no sub-routers - Effectively unmaintained (last release ~2020, v2 stalled) - Go 1.22 stdlib now covers its core value proposition ### Fiber (`github.com/gofiber/fiber`) ~39,300 GitHub stars. Express.js-inspired, built on fasthttp. **Pros:** - Very high raw throughput - Active development, large community - Route grouping and sub-routers **Cons:** - Built on fasthttp, NOT `net/http`. Fundamentally incompatible - Custom `fiber.Ctx` handler signature - `net/http` middleware requires lossy adaptor with known streaming bugs - Pools/reuses request contexts (values must not escape handler) - Heavy dependency footprint ### Echo (`github.com/labstack/echo`) ~32,200 GitHub stars. Full-featured framework, v5 released. **Pros:** - Active maintenance - Route grouping, sub-routers, built-in middleware suite - Echo instance implements `http.Handler` via `ServeHTTP` **Cons:** - Custom `echo.Context` handler signature - stdlib middleware requires `echo.WrapMiddleware` adapter - Framework wants to own request lifecycle, conflicts with LabKit's wrapper role - External dependencies (golang.org/x/crypto, golang.org/x/net) ### Gin (`github.com/gin-gonic/gin`) ~88,200 GitHub stars. Most popular Go framework. **Pros:** - Largest ecosystem and community - Route grouping, JSON binding, validation **Cons:** - Custom `*gin.Context` handler signature, not `http.Handler` compatible - stdlib middleware requires wrapping - Full framework, not a router (adds weight LabKit does not need) - Built on httprouter (unmaintained) as transitive dependency - Historical maintenance gaps ## Deliverable A pro/con recommendation with a decision on which router becomes the default `Router` implementation in `v2/httpserver`. The chosen router should be adoptable by all GitLab Go services (go-service-template, Artifact Registry, and future services). ## Related - httpserver MR: https://gitlab.com/gitlab-org/labkit/-/merge_requests/339 - httpserver design requirements: https://gitlab.com/gitlab-org/quality/quality-engineering/team-tasks/-/issues/4283 - Chi discussion issue: https://gitlab.com/gitlab-org/quality/quality-engineering/team-tasks/-/issues/4311 - Parent epic: https://gitlab.com/groups/gitlab-org/quality/-/epics/360 - Artifact Registry PoC feedback: https://gitlab.com/gitlab-org/gitlab/-/issues/590332#note_3128897716
issue