Skip to content

reverseproxy: isolate active health-check state per distinct check config - #7916

Open
SillyZir wants to merge 2 commits into
caddyserver:masterfrom
SillyZir:auto-fix/7870
Open

reverseproxy: isolate active health-check state per distinct check config#7916
SillyZir wants to merge 2 commits into
caddyserver:masterfrom
SillyZir:auto-fix/7870

Conversation

@SillyZir

@SillyZir SillyZir commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Fixes #7870.

Multiple reverse_proxy handlers configured with different active health checks (health_uri, health_headers, ...) against the same upstream dial address currently share a single Host in the global pool, so one handler's failing probes mark the address unhealthy for every other handler. This keys the pool by dial address plus a stable fingerprint of the active health-check config, so distinct checks get independent health state.

The fingerprint is strictly internal to pool identity:

  • the Prometheus upstreams_healthy label is untouched (still the plain Dial address);
  • the /reverse_proxy/upstreams admin endpoint strips the fingerprint at emission (hostKeyAddress), so API output reports plain dial addresses as before.

Scope note: dynamic upstreams are intentionally not covered here — they resolve through the separate per-lookup dynamicHosts path with different lifetime semantics, so the same collapse there is left for a follow-up rather than half-fixed in this change.

The regression test (TestActiveHealthChecksSameAddressDifferentChecksAreIndependent) spins up two handlers with different health_uri against one address and asserts vhost B's health state stays independent while vhost A's probes fail; it fails on master and passes with this change.

Files: modules/caddyhttp/reverseproxy/{healthchecks,hosts,reverseproxy,admin}.go, active_health_test.go

Assistance Disclosure
This patch was developed with AI assistance. It was reviewed and tested before submission (affected package tests pass), and is submitted from a human-owned account that takes responsibility for the change.

…nfig

Multiple reverse_proxy handlers configured with different active health
checks (health_uri, health_headers, ...) against the same upstream dial
address currently share a single Host in the global pool, so one
handler's failing probes mark the address unhealthy for every other
handler. Key the pool by dial address plus a stable fingerprint of the
active health-check config, so distinct checks get independent health
state.

The fingerprint is strictly internal to pool identity: the Prometheus
upstreams_healthy label and the /reverse_proxy/upstreams admin endpoint
continue to report the plain dial address, unchanged.

Dynamic upstreams are intentionally out of scope here: they resolve
through a separate per-lookup path (dynamicHosts) and collapsing there
has different lifetime semantics; noted for a follow-up.

Fixes caddyserver#7870
Satisfies the modernize linter; behaviour is unchanged, since Cut returns
the whole string when the separator is absent.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

reverse_proxy: different active health checks (health_uri/health_headers) against the same upstream address collapse into one shared health state

1 participant