Documentation
¶
Overview ¶
Package http provides an HTTP transport for the controls lifecycle controller, exposing health, readiness, and management endpoints for use with container orchestrators and load balancers.
Index ¶
- Constants
- func HealthHandler(controller controls.HealthReporter) http.HandlerFunc
- func LivenessHandler(controller controls.HealthReporter) http.HandlerFunc
- func MaxBytesMiddleware(maxBytes int64) func(http.Handler) http.Handler
- func NewClient(opts ...ClientOption) *http.Client
- func NewServer(ctx context.Context, cfg config.Containable, handler http.Handler, ...) (*http.Server, error)
- func NewTransport(tlsCfg *tls.Config) *http.Transport
- func ReadinessHandler(controller controls.HealthReporter) http.HandlerFunc
- func Register(ctx context.Context, id string, controller controls.Controllable, ...) (*http.Server, error)
- func Start(cfg config.Containable, logger logger.Logger, srv *http.Server, ...) controls.StartFunc
- func Status(srv *http.Server) controls.StatusFunc
- func Stop(logger logger.Logger, srv *http.Server) controls.StopFunc
- type Chain
- type ClientChain
- type ClientMiddleware
- type ClientOption
- func WithCertPool(pool *x509.CertPool) ClientOption
- func WithClientMiddleware(chain ClientChain) ClientOption
- func WithMaxRedirects(n int) ClientOption
- func WithRetry(cfg RetryConfig) ClientOption
- func WithTLSConfig(cfg *tls.Config) ClientOption
- func WithTimeout(d time.Duration) ClientOption
- func WithTransport(rt http.RoundTripper) ClientOption
- type LogFormat
- type LoggingOption
- type Middleware
- type RegisterOption
- type RetryConfig
- type ServerOption
- func WithConfigPrefix(prefix string) ServerOption
- func WithIdleTimeout(d time.Duration) ServerOption
- func WithMaxHeaderBytes(n int) ServerOption
- func WithPort(port int) ServerOption
- func WithReadTimeout(d time.Duration) ServerOption
- func WithServerTLSConfig(c *tls.Config) ServerOption
- func WithWriteTimeout(d time.Duration) ServerOption
Examples ¶
Constants ¶
const DefaultConfigPrefix = "server.http"
DefaultConfigPrefix is the config prefix an HTTP server reads (port, TLS, max_header_bytes) unless overridden with WithConfigPrefix.
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 HealthHandler ¶
func HealthHandler(controller controls.HealthReporter) http.HandlerFunc
HealthHandler returns an http.HandlerFunc that responds with the controller's health report.
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 NewClient ¶
func NewClient(opts ...ClientOption) *http.Client
NewClient returns an *http.Client with security-focused defaults: TLS 1.2 minimum, curated cipher suites, timeouts, connection limits, and redirect policy that rejects HTTPS-to-HTTP downgrades.
Example ¶
package main
import (
"time"
gtbhttp "gitlab.com/phpboyscout/go-tool-base/pkg/http"
)
func main() {
// Create a hardened HTTP client with security defaults.
client := gtbhttp.NewClient(
gtbhttp.WithTimeout(10*time.Second),
gtbhttp.WithMaxRedirects(5),
)
_ = client // Use like a standard *http.Client
}
Output:
Example (WithRetry) ¶
package main
import (
"time"
gtbhttp "gitlab.com/phpboyscout/go-tool-base/pkg/http"
)
func main() {
// Create a client with automatic retry for transient failures.
client := gtbhttp.NewClient(
gtbhttp.WithTimeout(30*time.Second),
gtbhttp.WithRetry(gtbhttp.RetryConfig{
MaxRetries: 3,
InitialBackoff: 500 * time.Millisecond,
MaxBackoff: 30 * time.Second,
}),
)
_ = client
}
Output:
func NewServer ¶
func NewServer(ctx context.Context, cfg config.Containable, handler http.Handler, opts ...ServerOption) (*http.Server, error)
NewServer returns a new preconfigured http.Server. With no options it reads from the default "server.http" config prefix; pass ServerOption values such as WithConfigPrefix or WithPort to run multiple independent servers.
func NewTransport ¶
NewTransport returns a preconfigured *http.Transport with security-focused defaults: curated TLS configuration, connection limits, and timeouts. If tlsCfg is nil, DefaultTLSConfig() is used.
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, cfg config.Containable, logger logger.Logger, handler http.Handler, opts ...any) (*http.Server, error)
Register creates a new HTTP server and registers it with the controller under the given id. The opts variadic accepts both ServerOption values (port, prefix, timeouts) and RegisterOption values (middleware, body limit) — other types are ignored. This mirrors the pkg/grpc Register signature.
func Start ¶
func Start(cfg config.Containable, logger logger.Logger, srv *http.Server, opts ...ServerOption) controls.StartFunc
Start returns a curried function suitable for use with the controls package. With no options it reads TLS from the default "server.http" config prefix; pass WithConfigPrefix to match a server constructed on a custom prefix.
Types ¶
type Chain ¶
type Chain struct {
// contains filtered or unexported fields
}
Chain composes zero or more Middleware into a single Middleware. Middleware is applied left-to-right: the first middleware in the list is the outermost wrapper (first to see the request, last to see the response).
chain := NewChain(recovery, logging, auth) handler := chain.Then(mux)
func NewChain ¶
func NewChain(middlewares ...Middleware) Chain
NewChain creates a new middleware chain from the given middleware functions. Nil entries are silently skipped.
func (Chain) Append ¶
func (c Chain) Append(middlewares ...Middleware) Chain
Append returns a new Chain with additional middleware appended. The original chain is not modified. Nil entries are silently skipped.
type ClientChain ¶
type ClientChain struct {
// contains filtered or unexported fields
}
ClientChain composes ClientMiddleware in order. Immutable — Append returns a new chain.
func NewClientChain ¶
func NewClientChain(middlewares ...ClientMiddleware) ClientChain
NewClientChain creates a ClientChain from the given middleware.
Example ¶
package main
import (
"os"
"time"
gtbhttp "gitlab.com/phpboyscout/go-tool-base/pkg/http"
"gitlab.com/phpboyscout/go-tool-base/pkg/logger"
)
func main() {
// Compose client middleware for auth, logging, and rate limiting.
chain := gtbhttp.NewClientChain(
gtbhttp.WithRequestLogging(logger.NewNoop()),
gtbhttp.WithBearerToken(os.Getenv("API_TOKEN")),
gtbhttp.WithRateLimit(10), // 10 requests per second
)
client := gtbhttp.NewClient(
gtbhttp.WithTimeout(30*time.Second),
gtbhttp.WithClientMiddleware(chain),
)
_ = client // Use like a standard *http.Client
}
Output:
func (ClientChain) Append ¶
func (c ClientChain) Append(middlewares ...ClientMiddleware) ClientChain
Append returns a new chain with additional middleware appended.
func (ClientChain) Then ¶
func (c ClientChain) Then(rt http.RoundTripper) http.RoundTripper
Then applies the middleware chain to the given RoundTripper and returns the wrapped result.
type ClientMiddleware ¶
type ClientMiddleware func(next http.RoundTripper) http.RoundTripper
ClientMiddleware wraps an http.RoundTripper with additional behaviour. The first middleware in a chain is the outermost wrapper — it executes first on the request and last on the response.
func WithBasicAuth ¶
func WithBasicAuth(username, password string) ClientMiddleware
WithBasicAuth returns middleware that injects an Authorization: Basic header on every request.
func WithBearerToken ¶
func WithBearerToken(token string) ClientMiddleware
WithBearerToken returns middleware that injects an Authorization: Bearer header on every request.
func WithRateLimit ¶
func WithRateLimit(requestsPerSecond float64) ClientMiddleware
WithRateLimit returns middleware that limits outbound requests to the specified rate using a token bucket algorithm. Blocks until a token is available or the request context is cancelled.
func WithRequestLogging ¶
func WithRequestLogging(log logger.Logger) ClientMiddleware
WithRequestLogging returns middleware that logs each outbound request and response at debug level. Logs method, URL, status code, and duration. Headers and body are NOT logged for security.
type ClientOption ¶
type ClientOption func(*clientConfig)
ClientOption configures the secure HTTP client.
func WithCertPool ¶ added in v0.8.0
func WithCertPool(pool *x509.CertPool) ClientOption
WithCertPool sets the root CA pool used to verify server certificates, preserving the hardened default TLS configuration (cipher suites, minimum version, curve preferences). Use this to trust certificates that are not in the system roots, such as a private CA or self-signed cert. Build the pool with tls.CertPool. Applying WithTLSConfig after this option replaces the pool along with the rest of the TLS configuration.
func WithClientMiddleware ¶
func WithClientMiddleware(chain ClientChain) ClientOption
WithClientMiddleware applies a middleware chain to the client's transport. The chain wraps the transport after retry (if configured) so that retry operates on the raw transport, not on logged/authed requests.
func WithMaxRedirects ¶
func WithMaxRedirects(n int) ClientOption
WithMaxRedirects sets the maximum number of redirects to follow. Default: 10. Set to 0 to disable redirect following entirely.
func WithRetry ¶
func WithRetry(cfg RetryConfig) ClientOption
WithRetry enables automatic retry with exponential backoff for transient failures.
func WithTLSConfig ¶
func WithTLSConfig(cfg *tls.Config) ClientOption
WithTLSConfig overrides the default TLS configuration. The caller is responsible for ensuring the provided config meets security requirements.
func WithTimeout ¶
func WithTimeout(d time.Duration) ClientOption
WithTimeout sets the overall request timeout. Default: 30s.
func WithTransport ¶
func WithTransport(rt http.RoundTripper) ClientOption
WithTransport overrides the entire HTTP transport. When set, transport-level options (TLS config, connection limits) are ignored.
type LogFormat ¶
type LogFormat int
LogFormat controls the output format of the logging middleware.
const ( // FormatStructured emits structured key-value fields via logger.Logger. FormatStructured LogFormat = iota // FormatCommon emits NCSA Common Log Format (CLF). FormatCommon // FormatCombined emits NCSA Combined Log Format (CLF + Referer + User-Agent). FormatCombined // FormatJSON emits a single JSON object per request. FormatJSON )
type LoggingOption ¶
type LoggingOption func(*loggingConfig)
LoggingOption configures transport logging behaviour.
func WithFormat ¶
func WithFormat(format LogFormat) LoggingOption
WithFormat sets the log output format. Defaults to FormatStructured.
func WithHeaderFields ¶
func WithHeaderFields(headers ...string) LoggingOption
WithHeaderFields logs the specified request header values as fields. Header names are normalised to lowercase. Values are truncated to 256 bytes.
Known-sensitive headers (Authorization, Cookie, Set-Cookie, X-Api-Key, X-Auth-Token, X-Csrf-Token, X-Session-Token, Proxy-Authorization) are always redacted regardless of whether they appear in the fields list. This is defence-in-depth against accidental credential leakage.
func WithLogLevel ¶
func WithLogLevel(level logger.Level) LoggingOption
WithLogLevel sets the log level for successful requests. Defaults to logger.InfoLevel. Errors always log at logger.ErrorLevel.
func WithPathFilter ¶
func WithPathFilter(paths ...string) LoggingOption
WithPathFilter excludes requests matching the given paths from logging.
func WithoutLatency ¶
func WithoutLatency() LoggingOption
WithoutLatency disables the "latency" field.
func WithoutUserAgent ¶
func WithoutUserAgent() LoggingOption
WithoutUserAgent disables the "user_agent" field.
type Middleware ¶
Middleware is the standard Go HTTP middleware signature.
func LoggingMiddleware ¶
func LoggingMiddleware(l logger.Logger, opts ...LoggingOption) Middleware
LoggingMiddleware returns an HTTP Middleware that logs each completed request.
func OTelMiddleware ¶ added in v0.7.0
func OTelMiddleware(server string, opts ...otelhttp.Option) Middleware
OTelMiddleware returns a Middleware that records an OpenTelemetry server span and the standard server metrics (http.server.*) for each request, reading whichever TracerProvider and MeterProvider are installed as the OTel globals (see telemetry.Setup). server names the span operation, identifying this service in the trace.
It composes in a Chain like any other middleware. Put it ahead of the logging middleware so the request log can pick up the active span:
chain := http.NewChain(
http.OTelMiddleware("macguffin"),
http.LoggingMiddleware(log),
)
type RegisterOption ¶
type RegisterOption func(*registerConfig)
RegisterOption configures registration-only behaviour for an HTTP server (middleware chain, request-body limit). Server construction settings — port, prefix, 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 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 RetryConfig ¶
type RetryConfig struct {
// MaxRetries is the maximum number of retry attempts. Zero means no retries.
MaxRetries int
// InitialBackoff is the base delay before the first retry. Default: 500ms.
InitialBackoff time.Duration
// MaxBackoff caps the computed delay. Default: 30s.
MaxBackoff time.Duration
// RetryableStatusCodes defines which HTTP status codes trigger a retry.
// Default: []int{429, 502, 503, 504}.
RetryableStatusCodes []int
// ShouldRetry is an optional custom predicate. When set, it replaces the
// default status-code and network-error checks. The attempt count (0-based)
// and either the response or the transport error are provided.
ShouldRetry func(attempt int, resp *http.Response, err error) bool
}
RetryConfig configures the retry behaviour of the HTTP client.
func DefaultRetryConfig ¶
func DefaultRetryConfig() RetryConfig
DefaultRetryConfig returns a RetryConfig suitable for most use cases.
type ServerOption ¶ added in v0.9.0
type ServerOption func(*serverConfig)
ServerOption configures an HTTP server built by NewServer or started by Start. ServerOption values are also accepted by Register.
func WithConfigPrefix ¶ added in v0.6.0
func WithConfigPrefix(prefix string) ServerOption
WithConfigPrefix sets the config prefix the server reads its port, TLS and max_header_bytes from (default "server.http"). Use it to run a second HTTP server on its own config block, e.g. "server.admin" for an internal server.
When constructing a server outside Register, pass the SAME prefix to both NewServer and Start so the listen port and TLS settings stay consistent.
func WithIdleTimeout ¶ added in v0.9.0
func WithIdleTimeout(d time.Duration) ServerOption
WithIdleTimeout overrides the built-in http.Server IdleTimeout.
func WithMaxHeaderBytes ¶ added in v0.9.0
func WithMaxHeaderBytes(n int) ServerOption
WithMaxHeaderBytes overrides <prefix>.max_header_bytes and the built-in 1 MB default for the constructed server's MaxHeaderBytes.
func WithPort ¶ added in v0.9.0
func WithPort(port int) ServerOption
WithPort sets the listen port explicitly, bypassing config lookup entirely. It has the highest precedence: it overrides both <prefix>.port and the server.port shared fallback.
func WithReadTimeout ¶ added in v0.9.0
func WithReadTimeout(d time.Duration) ServerOption
WithReadTimeout overrides the built-in http.Server ReadTimeout.
func WithServerTLSConfig ¶ added in v0.9.0
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 server's TLS config prefix). It is named distinctly from the client-side WithTLSConfig option in this package.
func WithWriteTimeout ¶ added in v0.9.0
func WithWriteTimeout(d time.Duration) ServerOption
WithWriteTimeout overrides the built-in http.Server WriteTimeout.