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