HTTP server
The server
package wraps the standard library with graceful shutdown. The listener is bound
at construction, so the address is available immediately, but serving does not
begin until you call ServeHTTP/ServeHTTPHandler — which block until the
context is cancelled.
srv, err := server.New("8080") // empty string lets the OS choose a port
if err != nil {
return err
}
log.Printf("listening on %s", srv.Addr())
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer cancel()
// Blocks until ctx is cancelled, then shuts down with a 5s grace period.
return srv.ServeHTTPHandler(ctx, handler)
ServeHTTPHandler builds an http.Server with a sensible
ReadHeaderTimeout. If you need full control (custom timeouts, TLS config, an
observability wrapper around the handler), build your own *http.Server and call
ServeHTTP instead:
return srv.ServeHTTP(ctx, &http.Server{
ReadHeaderTimeout: 5 * time.Second,
Handler: myWrappedHandler,
})
Observability is intentionally not built in — wrap your handler with whatever
tracing/metrics middleware you use before passing it in. Shutdown errors are
aggregated with the standard library’s errors.Join.
Health endpoints
The package ships Kubernetes-style probe handlers:
r.Handle("/healthz", server.HealthzHandler()) // liveness: always 200 {"status":"ok"}
r.Handle("/readyz", server.ReadyzHandler(map[string]func(context.Context) error{
"database": func(ctx context.Context) error { return db.PingContext(ctx) },
}))
ReadyzHandler runs every named check with the request context. If all pass it
responds 200 {"status":"ok"}; otherwise 503 listing the failing check
names — error details are logged server-side and never returned in the body, so
a publicly-reachable probe can’t leak internal hostnames or paths:
{"status":"unavailable","failed":["database"]}
A check that panics is treated as failed rather than crashing the probe. Checks
should be fast and side-effect free; wrap slow checks in your own caching (the
cache package works well) if probes are frequent.