http

package
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 17, 2026 License: MIT Imports: 17 Imported by: 0

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

View Source
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

func IdentityFromContext(ctx context.Context) (*authn.Identity, bool)

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

func MaxBytesMiddleware(maxBytes int64) func(http.Handler) http.Handler

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

func StartWithTLSPair(logger *slog.Logger, srv *http.Server, tlsPair gtls.Pair) controls.StartFunc

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

func Stop(logger *slog.Logger, srv *http.Server) controls.StopFunc

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL