Open-Source Wikis

/

Caddy

/

Features

/

Reverse proxy

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| Health

Selection 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): a caddyhttp.RoundTripper wrapping net/http's Transport. Supports H2C, HTTP/2, HTTP/3 (via quic-go), TLS verification toggles, dialer timeouts, custom TLS config (including client certs).
  • FastCGI transport (fastcgi/): registered as http.reverse_proxy.transport.fastcgi. Used by the php_fastcgi Caddyfile 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: chunked upstream → 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

  • http app: registered as a handler module; consumes the same Replacer, response-writer, and route plumbing as every other handler.
  • TLS: transports can carry their own tls.ConnectionPolicy for upstream TLS (mTLS to the backend, custom CAs, …).
  • Admin API: /reverse_proxy/upstreams exposes 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 + one init() registration). Tests in selectionpolicies_test.go are exhaustive and a good model.
  • New upstream source? Implement UpstreamSource in upstreams.go style and register http.reverse_proxy.upstreams.<name>.
  • New transport? Implement caddyhttp.RoundTripper and register http.reverse_proxy.transport.<name>.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Reverse proxy – Caddy wiki | Factory