LabKit v2: httpserver package

Overview

Implement the httpserver package for LabKit v2 — a production-ready HTTP server that implements app.Component and ships with automatic liveness/readiness probes.

The package must be designed so the underlying HTTP framework can be swapped without breaking consumers. All framework-specific details (routing, middleware chaining, request/response types) should be hidden behind LabKit-owned interfaces and types. Consumers interact only with the public httpserver API; the concrete router/server implementation is an internal detail.

Design requirements for framework swappability

  • Abstract router interface — Expose a Router interface (e.g. Handle, HandleFunc, Use) that the package satisfies. The current implementation may use net/http, Chi, Gorilla, or any other router internally, but callers never import it directly.
  • Middleware as func(http.Handler) http.Handler — Stick to the standard net/http middleware signature so middleware works regardless of the underlying router.
  • No framework types in the public API — All public function signatures, config structs, and option types must use only stdlib or LabKit-defined types. Framework-specific adapters live in an internal/ sub-package.
  • Constructor injection — Allow advanced users to supply a custom Router implementation via httpserver.Config (optional; a sensible default is provided).
  • Integration tests against the interface — Tests should exercise the Router interface, not a concrete framework, so swapping the implementation only requires updating the internal adapter.

/-/liveness and /-/readiness are registered automatically. Readiness checks are chainable and run concurrently.

Example usage

srv := httpserver.NewWithConfig(&httpserver.Config{
    Addr:            ":8080",
    ShutdownTimeout: 30 * time.Second,
    Logger:          logger,
    Tracer:          tracer,
    // Optional: supply a custom router implementation
    // Router:       mychirouter.New(),
})

srv.AddReadinessCheck("database", db.Pool().Ping)
srv.Router().HandleFunc("/api/v1/projects", handleProjects)

Reference

Edited by Elliot Forbes