reverseproxy: save dial info in a context key instead of a variable key to avoid race conditions when forward_auth is used (#7859)
parent
945d199724
commit
1830809afe
|
|
@ -438,9 +438,7 @@ func (h *Handler) doActiveHealthCheck(dialInfo DialInfo, hostAddr string, networ
|
|||
// may be expected by handlers of this request
|
||||
ctx := h.ctx.Context
|
||||
ctx = context.WithValue(ctx, caddy.ReplacerCtxKey, caddy.NewReplacer())
|
||||
ctx = context.WithValue(ctx, caddyhttp.VarsCtxKey, map[string]any{
|
||||
dialInfoVarKey: dialInfo,
|
||||
})
|
||||
ctx = context.WithValue(ctx, dialInfoCtxKey, dialInfo)
|
||||
req, err := http.NewRequestWithContext(ctx, h.HealthChecks.Active.Method, u.String(), requestBody)
|
||||
if err != nil {
|
||||
return fmt.Errorf("making request: %v", err)
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/caddyserver/caddy/v2"
|
||||
"github.com/caddyserver/caddy/v2/modules/caddyhttp"
|
||||
)
|
||||
|
||||
// UpstreamPool is a collection of upstreams.
|
||||
|
|
@ -297,7 +296,7 @@ func (di DialInfo) String() string {
|
|||
// GetDialInfo gets the upstream dialing info out of the context,
|
||||
// and returns true if there was a valid value; false otherwise.
|
||||
func GetDialInfo(ctx context.Context) (DialInfo, bool) {
|
||||
dialInfo, ok := caddyhttp.GetVar(ctx, dialInfoVarKey).(DialInfo)
|
||||
dialInfo, ok := ctx.Value(dialInfoCtxKey).(DialInfo)
|
||||
return dialInfo, ok
|
||||
}
|
||||
|
||||
|
|
@ -329,9 +328,9 @@ type dynamicHostEntry struct {
|
|||
lastSeen time.Time
|
||||
}
|
||||
|
||||
// dialInfoVarKey is the key used for the variable that holds
|
||||
// dialInfoCtxKey is the context key used for the variable that holds
|
||||
// the dial info for the upstream connection.
|
||||
const dialInfoVarKey = "reverse_proxy.dial_info"
|
||||
const dialInfoCtxKey caddy.CtxKey = "reverse_proxy.dial_info"
|
||||
|
||||
// proxyProtocolInfoVarKey is the key used for the variable that holds
|
||||
// the proxy protocol info for the upstream connection.
|
||||
|
|
|
|||
|
|
@ -260,7 +260,7 @@ func TestHTTPTransport_DialContext_DialInfoOverride(t *testing.T) {
|
|||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
dialCtx := context.WithValue(context.Background(), caddyhttp.VarsCtxKey, make(map[string]any))
|
||||
caddyhttp.SetVar(dialCtx, dialInfoVarKey, DialInfo{
|
||||
dialCtx = context.WithValue(dialCtx, dialInfoCtxKey, DialInfo{
|
||||
Network: "tcp4",
|
||||
Address: tt.dialInfo,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -660,11 +660,6 @@ func (h *Handler) proxyLoopIteration(r *http.Request, origReq *http.Request, w h
|
|||
)
|
||||
}
|
||||
|
||||
// attach to the request information about how to dial the upstream;
|
||||
// this is necessary because the information cannot be sufficiently
|
||||
// or satisfactorily represented in a URL
|
||||
caddyhttp.SetVar(r.Context(), dialInfoVarKey, dialInfo)
|
||||
|
||||
// set placeholders with information about this upstream
|
||||
repl.Set("http.reverse_proxy.upstream.address", dialInfo.String())
|
||||
repl.Set("http.reverse_proxy.upstream.hostport", dialInfo.Address)
|
||||
|
|
@ -1037,7 +1032,14 @@ func (h *Handler) reverseProxy(rw http.ResponseWriter, req *http.Request, origRe
|
|||
return nil
|
||||
},
|
||||
}
|
||||
req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))
|
||||
// attach to the request information about how to dial the upstream;
|
||||
// this is necessary because the information cannot be sufficiently
|
||||
// or satisfactorily represented in a URL
|
||||
// it's set before request is roundtripped to avoid a race condition when
|
||||
// http.Transport reads a newer value to dial a new connection when that new
|
||||
// value is updated by another reverse proxy handler, typically forward_auth.
|
||||
ctx := context.WithValue(req.Context(), dialInfoCtxKey, di)
|
||||
req = req.WithContext(httptrace.WithClientTrace(ctx, trace))
|
||||
|
||||
// do the round-trip
|
||||
start := time.Now()
|
||||
|
|
|
|||
Loading…
Reference in New Issue