Documentation
¶
Overview ¶
Package http provides a hardened HTTP server toolkit.
It bootstraps an HTTP server that integrates with the gitlab.com/phpboyscout/go/controls lifecycle and exposes health, liveness and readiness handlers, plus request authentication (AuthMiddleware, from gitlab.com/phpboyscout/go/authn) and SecurityHeadersMiddleware. Servers are constructed from the package-owned typed ServerSettings via NewServer or wired into a supervised service with Register; StartWithTLSPair, Stop and Status expose the lifecycle as controls primitives.
The request-logging, OpenTelemetry, rate-limiting and circuit-breaker middleware this server composes live in gitlab.com/phpboyscout/go/transit and are applied through a transit http.Chain. Framework config integration (the *FromContainable settings adapters) lives in go-tool-base's pkg/http, not here, so this package never imports the framework config container.
Index ¶
- Constants
- func AuthMiddleware(opts ...AuthOption) (transithttp.Middleware, error)
- func HealthHandler(controller controls.HealthReporter) http.HandlerFunc
- func IdentityFromContext(ctx context.Context) (*authn.Identity, bool)
- func LivenessHandler(controller controls.HealthReporter) http.HandlerFunc
- func MaxBytesMiddleware(maxBytes int64) func(http.Handler) http.Handler
- func NewServer(ctx context.Context, settings ServerSettings, handler http.Handler, ...) (*http.Server, error)
- func ReadinessHandler(controller controls.HealthReporter) http.HandlerFunc
- func Register(ctx context.Context, id string, controller controls.Controllable, ...) (*http.Server, error)
- func SecurityHeadersMiddleware(opts ...SecurityHeadersOption) transithttp.Middleware
- func StartWithTLSPair(logger *slog.Logger, srv *http.Server, tlsPair gtls.Pair) controls.StartFunc
- func Status(srv *http.Server) controls.StatusFunc
- func Stop(logger *slog.Logger, srv *http.Server) controls.StopFunc
- type AuthOption
- func WithAPIKeyHeader(header string, v authn.Verifier) AuthOption
- func WithAuthLogger(l *slog.Logger) AuthOption
- func WithAuthSkipper(pred func(*http.Request) bool) AuthOption
- func WithAuthorize(fn authn.AuthorizeFunc) AuthOption
- func WithBearerVerifier(v authn.Verifier) AuthOption
- func WithCookieVerifier(cookieName string, v authn.Verifier) AuthOption
- func WithMTLSVerifier(v authn.CertVerifier) AuthOption
- type RegisterOption
- type SecurityHeadersOption
- func WithContentSecurityPolicy(policy string) SecurityHeadersOption
- func WithContentTypeOptions(value string) SecurityHeadersOption
- func WithFrameOptions(value string) SecurityHeadersOption
- func WithHSTS(maxAge time.Duration, includeSubdomains, preload bool) SecurityHeadersOption
- func WithReferrerPolicy(policy string) SecurityHeadersOption
- type ServerOption
- type ServerSettings
- type ServerSettingsSource
Constants ¶
const ( // DefaultMaxRequestBodyBytes caps the size of each request body // accepted by the management HTTP server. Closes M-1 from // docs/development/reports/security-audit-2026-04-17.md. DefaultMaxRequestBodyBytes int64 = 1 << 20 // 1 MiB )
Variables ¶
This section is empty.
Functions ¶
func AuthMiddleware ¶
func AuthMiddleware(opts ...AuthOption) (transithttp.Middleware, error)
AuthMiddleware returns a transithttp.Middleware that authenticates (and optionally authorizes) each request, storing the verified Identity in the request context on success. With no verifier configured it is a construction error (fail-closed; never a silent pass-through).
Credential precedence: a bearer token and an API-key header presented together are rejected as ambiguous (fail-closed). Otherwise the presented header scheme is used; mTLS authenticates only when no header credential is presented.
On failure the middleware writes a generic 401 (with WWW-Authenticate) or 403 and never discloses why — the specific cause is logged once at WARN with the credential redacted. The handler is not invoked on failure.
func HealthHandler ¶
func HealthHandler(controller controls.HealthReporter) http.HandlerFunc
HealthHandler returns an http.HandlerFunc that responds with the controller's health report.
func IdentityFromContext ¶
IdentityFromContext returns the verified Identity set by AuthMiddleware. The same key is shared with the gRPC interceptor, so a handler reads identity the same way regardless of transport.
func LivenessHandler ¶
func LivenessHandler(controller controls.HealthReporter) http.HandlerFunc
LivenessHandler returns an http.HandlerFunc that responds with the controller's liveness report.
func MaxBytesMiddleware ¶
MaxBytesMiddleware wraps a handler so every request body is bounded by http.MaxBytesReader. A request that exceeds the limit is terminated with HTTP 413 (via the default ResponseWriter behaviour) when the handler attempts to read past the boundary.
Callers that need per-route limits should wrap the handler directly rather than registering at server level.
func NewServer ¶
func NewServer(ctx context.Context, settings ServerSettings, handler http.Handler, opts ...ServerOption) (*http.Server, error)
NewServer returns a new preconfigured http.Server from explicit typed settings.
func ReadinessHandler ¶
func ReadinessHandler(controller controls.HealthReporter) http.HandlerFunc
ReadinessHandler returns an http.HandlerFunc that responds with the controller's readiness report.
func Register ¶
func Register( ctx context.Context, id string, controller controls.Controllable, logger *slog.Logger, handler http.Handler, settings ServerSettings, tlsPair gtls.Pair, opts ...any, ) (*http.Server, error)
Register creates a new HTTP server from explicit typed settings and registers it with the controller under the given id.
func SecurityHeadersMiddleware ¶
func SecurityHeadersMiddleware(opts ...SecurityHeadersOption) transithttp.Middleware
SecurityHeadersMiddleware returns a transithttp.Middleware that sets a conservative set of response security headers on every request:
- X-Content-Type-Options: nosniff
- X-Frame-Options: DENY
- Content-Security-Policy: frame-ancestors 'none'
- Referrer-Policy: no-referrer
HSTS and a full CSP are opt-in via WithHSTS and WithContentSecurityPolicy. HSTS is off by default because it is only meaningful over TLS.
Headers are set before the wrapped handler runs so a handler that writes its own response (and may call WriteHeader) still emits them. A handler is free to override any of these by setting its own value.
The built-in docs/openapi handlers apply this middleware by default; it is not forced onto user-supplied handlers.
func StartWithTLSPair ¶
StartWithTLSPair returns a curried function suitable for use with the controls package from explicit TLS settings.
func Status ¶
func Status(srv *http.Server) controls.StatusFunc
Status returns a curried health function for a manually-wired server. It reports an error only when srv is nil; use the controller wiring (Serve) for serve-goroutine death detection.
func Stop ¶
Stop returns a curried function suitable for use with the controls package. Shutdown is attempted first to drain in-flight requests. If the shutdown context expires (or Shutdown otherwise errors) the server is force-closed via Close so a hung handler cannot leave the listener and connections open, mirroring the gRPC transport's graceful-then-force-stop behaviour.
Types ¶
type AuthOption ¶
type AuthOption func(*authConfig)
AuthOption configures AuthMiddleware.
func WithAPIKeyHeader ¶
func WithAPIKeyHeader(header string, v authn.Verifier) AuthOption
WithAPIKeyHeader extracts the credential from the named header (e.g. "X-API-Key") and verifies it with v.
func WithAuthLogger ¶
func WithAuthLogger(l *slog.Logger) AuthOption
WithAuthLogger sets the logger for redacted server-side auth failure logging.
func WithAuthSkipper ¶
func WithAuthSkipper(pred func(*http.Request) bool) AuthOption
WithAuthSkipper skips auth for requests matching pred (e.g. an OPTIONS preflight or a public sub-path). Health endpoints are already outside the chain and need no skipper.
func WithAuthorize ¶
func WithAuthorize(fn authn.AuthorizeFunc) AuthOption
WithAuthorize installs an authorization predicate run after verification.
func WithBearerVerifier ¶
func WithBearerVerifier(v authn.Verifier) AuthOption
WithBearerVerifier extracts a token from "Authorization: Bearer <token>" and verifies it with v.
func WithCookieVerifier ¶
func WithCookieVerifier(cookieName string, v authn.Verifier) AuthOption
WithCookieVerifier extracts the credential from the named cookie and verifies it with v. The cookie is an AMBIENT credential — the browser sends it on every request, including <img>/<audio>/<video> sub-resource loads that cannot set an Authorization header — so it sits BELOW the explicit header schemes in precedence: an explicit bearer or API-key header always wins, and the cookie is consulted only when no header credential is presented. This lets a browser session authenticate sub-resources while leaving explicit API clients unaffected. Typically paired with a token-in-URL bootstrap that sets the cookie on first load (Jupyter-style).
func WithMTLSVerifier ¶
func WithMTLSVerifier(v authn.CertVerifier) AuthOption
WithMTLSVerifier authenticates the request from its verified client certificate when no header credential is presented. The server must be configured for client-cert verification (RequireAndVerifyClientCert).
type RegisterOption ¶
type RegisterOption func(*registerConfig)
RegisterOption configures registration-only behaviour for an HTTP server (middleware chain, request-body limit). Server construction settings — port, timeouts — are ServerOption values; Register accepts both families.
func WithMaxRequestBodyBytes ¶
func WithMaxRequestBodyBytes(n int64) RegisterOption
WithMaxRequestBodyBytes overrides the DefaultMaxRequestBodyBytes cap applied to every request body. Set to a negative value to disable the cap entirely (not recommended).
func WithMiddleware ¶
func WithMiddleware(chain transithttp.Chain) RegisterOption
WithMiddleware sets the middleware chain applied to the handler before it is passed to the HTTP server. Health endpoints (/healthz, /livez, /readyz) are mounted outside the chain and are never affected by middleware.
type SecurityHeadersOption ¶
type SecurityHeadersOption func(*securityHeadersConfig)
SecurityHeadersOption configures SecurityHeadersMiddleware.
func WithContentSecurityPolicy ¶
func WithContentSecurityPolicy(policy string) SecurityHeadersOption
WithContentSecurityPolicy sets a full Content-Security-Policy header value, replacing the conservative default ("frame-ancestors 'none'"). The caller owns the complete policy when this option is supplied. An empty value falls back to the frame-ancestors-only default so the clickjacking control is never silently dropped.
func WithContentTypeOptions ¶
func WithContentTypeOptions(value string) SecurityHeadersOption
WithContentTypeOptions overrides the X-Content-Type-Options header value (default "nosniff"). An empty value omits the header (not recommended).
func WithFrameOptions ¶
func WithFrameOptions(value string) SecurityHeadersOption
WithFrameOptions overrides the X-Frame-Options header value (default "DENY"). An empty value omits the header; the Content-Security-Policy frame-ancestors directive is unaffected.
func WithHSTS ¶
func WithHSTS(maxAge time.Duration, includeSubdomains, preload bool) SecurityHeadersOption
WithHSTS enables Strict-Transport-Security with the given max-age. HSTS is OFF by default because it is only meaningful over TLS; enable it only on a server that is exclusively reachable over HTTPS. A non-positive maxAge leaves HSTS disabled.
func WithReferrerPolicy ¶
func WithReferrerPolicy(policy string) SecurityHeadersOption
WithReferrerPolicy overrides the Referrer-Policy header value (default "no-referrer"). An empty value omits the header.
type ServerOption ¶
type ServerOption func(*serverConfig)
ServerOption configures an HTTP server built by NewServer or started by Start. ServerOption values are also accepted by Register.
func WithIdleTimeout ¶
func WithIdleTimeout(d time.Duration) ServerOption
WithIdleTimeout overrides the built-in http.Server IdleTimeout.
func WithMaxHeaderBytes ¶
func WithMaxHeaderBytes(n int) ServerOption
WithMaxHeaderBytes overrides the ServerSettings max_header_bytes and the built-in 1 MB default for the constructed server's MaxHeaderBytes.
func WithPort ¶
func WithPort(port int) ServerOption
WithPort sets the listen port explicitly, overriding the port carried in the typed ServerSettings.
func WithReadTimeout ¶
func WithReadTimeout(d time.Duration) ServerOption
WithReadTimeout overrides the built-in http.Server ReadTimeout.
func WithServerTLSConfig ¶
func WithServerTLSConfig(c *tls.Config) ServerOption
WithServerTLSConfig replaces the default hardened *tls.Config on the constructed server. Cert/key resolution for serving still flows through Start (from the supplied TLS pair). It is named distinctly from the client-side WithTLSConfig option in this package.
func WithWriteTimeout ¶
func WithWriteTimeout(d time.Duration) ServerOption
WithWriteTimeout overrides the built-in http.Server WriteTimeout.
type ServerSettings ¶
type ServerSettings struct {
Port int `mapstructure:"port" yaml:"port" json:"port"`
MaxHeaderBytes int `mapstructure:"max_header_bytes" yaml:"max_header_bytes" json:"max_header_bytes"`
}
ServerSettings contains the data needed to construct an HTTP server without binding the core constructor to any particular config system.
type ServerSettingsSource ¶
type ServerSettingsSource interface {
Current() *ServerSettings
Version() uint64
}
ServerSettingsSource exposes the latest HTTP server settings snapshot to packages that need reload-aware access without depending on GTB config.