caddyserver/caddy
Reverse proxy
http.handlers.reverse_proxy is the largest single Go file in the repo (modules/caddyhttp/reverseproxy/reverseproxy.go, ~68 KB). It is also the single most heavily used handler outside of the file server.
Purpose
Forward HTTP requests to one or more upstream servers, with:
- Pluggable transports (HTTP/1.1, HTTP/2, HTTP/3 via h2c, FastCGI).
- Health checks (active and passive).
- Selection policies (round-robin, least-conn, IP hash, header, cookie, random, weighted).
- Streaming for WebSockets and Server-Sent Events.
- Header rewriting, retries, fail-over.
- Forward auth via
http.handlers.forward_auth(forwardauth/).
Directory layout
| Path | Role |
|---|---|
modules/caddyhttp/reverseproxy/reverseproxy.go |
The handler itself: provisioning, request lifecycle, response handling |
modules/caddyhttp/reverseproxy/httptransport.go |
HTTP/1.1, HTTP/2, HTTP/3 transport configuration (~32 KB) |
modules/caddyhttp/reverseproxy/streaming.go |
WebSocket, SSE, hijacked streams (~21 KB) |
modules/caddyhttp/reverseproxy/upstreams.go |
Static + dynamic upstream resolution (~17 KB) |
modules/caddyhttp/reverseproxy/healthchecks.go |
Active and passive health checks (~21 KB) |
modules/caddyhttp/reverseproxy/selectionpolicies.go |
Load-balancing policies (~26 KB) |
modules/caddyhttp/reverseproxy/hosts.go |
The Host/Upstream data model |
modules/caddyhttp/reverseproxy/copyresponse.go |
Used by the intercept handler |
modules/caddyhttp/reverseproxy/admin.go |
Admin API: /reverse_proxy/upstreams |
modules/caddyhttp/reverseproxy/caddyfile.go |
Caddyfile parsing (reverse_proxy directive) |
modules/caddyhttp/reverseproxy/fastcgi/ |
FastCGI transport (PHP-FPM and friends) |
modules/caddyhttp/reverseproxy/forwardauth/ |
http.handlers.forward_auth (Authelia / Authentik / etc.) |
Key abstractions
| Type | Where | Description |
|---|---|---|
Handler |
reverseproxy.go |
The reverse proxy handler module |
Upstream |
hosts.go |
One backend; tracks unhealthy state, in-flight count, fail count |
UpstreamSource |
upstreams.go |
Module that resolves upstreams dynamically (DNS-A, SRV, etc.) |
Selector |
selectionpolicies.go |
Module that picks an upstream from the candidate set |
HTTPTransport |
httptransport.go |
Transport for HTTP/1, HTTP/2, HTTP/3 with TLS, dialer, timeouts |
Health |
healthchecks.go |
Active health check config; passive check counters |
How it works
graph TD
Req[HTTP request] --> Handler[reverse_proxy handler]
Handler -->|resolve upstreams| Upstreams
Upstreams -->|static| Static[static list]
Upstreams -->|dynamic| Source[UpstreamSource modules]
Handler -->|select| Selector
Selector -->|policy| Pick[Upstream]
Handler -->|round trip| Transport[HTTPTransport / FastCGI]
Transport -->|stream / proxy| Backend
Backend -->|response| Transport
Transport --> Handler
Handler -->|copy + rewrite headers| Resp[response]
Health[Active health checks] -->|mark up/down| Upstream
Resp -->|count failures| HealthSelection policies
All under http.reverse_proxy.selection_policies.*:
first— pick the first available.round_robin— cycle through upstreams.random/random_choose— uniform random or random-of-N.least_conn— fewest in-flight requests.ip_hash,client_ip_hash— consistent hash on client IP.header— hash on a request header value.cookie— sticky-session cookie issued by Caddy.uri_hash— hash on URI path.weighted_round_robin— weighted variant.
selectionpolicies.go implements them all in one file with one struct each.
Transports
- HTTP transport (
httptransport.go): acaddyhttp.RoundTripperwrappingnet/http'sTransport. Supports H2C, HTTP/2, HTTP/3 (viaquic-go), TLS verification toggles, dialer timeouts, custom TLS config (including client certs). - FastCGI transport (
fastcgi/): registered ashttp.reverse_proxy.transport.fastcgi. Used by thephp_fastcgiCaddyfile shorthand.
Health checks
healthchecks.go does:
- Active checks: a goroutine per upstream periodically GETs a configurable URL and inspects status, body, latency.
- Passive checks: counters incremented on request failures; an upstream is marked unhealthy after N consecutive failures and held there for a cool-down period.
The current health is exposed via the admin API at /reverse_proxy/upstreams (registered in admin.go).
Streaming
streaming.go handles long-lived bidirectional streams:
- WebSockets (
Upgrade: websocket). - Server-Sent Events.
Transfer-Encoding: chunkedupstream → downstream.- Hijacked HTTP/2 streams.
It uses io.Copy with periodic flushes and tracks active streams for graceful shutdown.
Forward auth
forwardauth/ registers http.handlers.forward_auth — a tiny wrapper that proxies the request to an auth service first, copies a configurable set of response headers back into the original request, and then continues the chain. Used for Authelia/Authentik/oauth2-proxy patterns.
Integration points
httpapp: registered as a handler module; consumes the sameReplacer, response-writer, and route plumbing as every other handler.- TLS: transports can carry their own
tls.ConnectionPolicyfor upstream TLS (mTLS to the backend, custom CAs, …). - Admin API:
/reverse_proxy/upstreamsexposes live upstream health. - Metrics: Prometheus counters for proxied requests, errors, and per-upstream activity.
Entry points for modification
- New selection policy? Add it in
selectionpolicies.go(one struct + oneinit()registration). Tests inselectionpolicies_test.goare exhaustive and a good model. - New upstream source? Implement
UpstreamSourceinupstreams.gostyle and registerhttp.reverse_proxy.upstreams.<name>. - New transport? Implement
caddyhttp.RoundTripperand registerhttp.reverse_proxy.transport.<name>.
Related pages
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.