reverseproxy: Add valid Upstream to DialInfo in active health checks (#6949)

Currently if we extract the DialInfo from a Request Context during an active health check, then the Upstream in the DialInfo is nil.

This PR attempts to set the Upstream to a sensible value, based on wether or not the Upstream has been overriden in the active health check's config.
pull/6802/head^2
Jesper Brix Rosenkilde 2025-04-15 16:44:53 +02:00 committed by GitHub
parent def9db1f16
commit 6c38ae7381
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 17 additions and 7 deletions

View File

@ -309,7 +309,9 @@ func (h *Handler) doActiveHealthCheckForAllHosts() {
}
}()
networkAddr, err := caddy.NewReplacer().ReplaceOrErr(upstream.Dial, true, true)
repl := caddy.NewReplacer()
networkAddr, err := repl.ReplaceOrErr(upstream.Dial, true, true)
if err != nil {
if c := h.HealthChecks.Active.logger.Check(zapcore.ErrorLevel, "invalid use of placeholders in dial address for active health checks"); c != nil {
c.Write(
@ -344,14 +346,24 @@ func (h *Handler) doActiveHealthCheckForAllHosts() {
return
}
hostAddr := addr.JoinHostPort(0)
dialAddr := hostAddr
if addr.IsUnixNetwork() || addr.IsFdNetwork() {
// this will be used as the Host portion of a http.Request URL, and
// paths to socket files would produce an error when creating URL,
// so use a fake Host value instead; unix sockets are usually local
hostAddr = "localhost"
}
err = h.doActiveHealthCheck(DialInfo{Network: addr.Network, Address: dialAddr}, hostAddr, networkAddr, upstream)
// Fill in the dial info for the upstream
// If the upstream is set, use that instead
dialInfoUpstream := upstream
if h.HealthChecks.Active.Upstream != "" {
dialInfoUpstream = &Upstream{
Dial: h.HealthChecks.Active.Upstream,
}
}
dialInfo, _ := dialInfoUpstream.fillDialInfo(repl)
err = h.doActiveHealthCheck(dialInfo, hostAddr, networkAddr, upstream)
if err != nil {
if c := h.HealthChecks.Active.logger.Check(zapcore.ErrorLevel, "active health check failed"); c != nil {
c.Write(

View File

@ -17,7 +17,6 @@ package reverseproxy
import (
"context"
"fmt"
"net/http"
"net/netip"
"strconv"
"sync/atomic"
@ -100,8 +99,7 @@ func (u *Upstream) Full() bool {
// fillDialInfo returns a filled DialInfo for upstream u, using the request
// context. Note that the returned value is not a pointer.
func (u *Upstream) fillDialInfo(r *http.Request) (DialInfo, error) {
repl := r.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer)
func (u *Upstream) fillDialInfo(repl *caddy.Replacer) (DialInfo, error) {
var addr caddy.NetworkAddress
// use provided dial address

View File

@ -532,7 +532,7 @@ func (h *Handler) proxyLoopIteration(r *http.Request, origReq *http.Request, w h
// the dial address may vary per-request if placeholders are
// used, so perform those replacements here; the resulting
// DialInfo struct should have valid network address syntax
dialInfo, err := upstream.fillDialInfo(r)
dialInfo, err := upstream.fillDialInfo(repl)
if err != nil {
return true, fmt.Errorf("making dial info: %v", err)
}