mirror of
https://github.com/caddyserver/caddy.git
synced 2024-12-16 21:56:40 -05:00
reverseproxy: Ignore context cancel in stream mode (#4952)
This commit is contained in:
parent
922d9f5c25
commit
f5dce84a70
1 changed files with 27 additions and 0 deletions
|
@ -109,6 +109,11 @@ type Handler struct {
|
|||
// response is recognized as a streaming response, or if its
|
||||
// content length is -1; for such responses, writes are flushed
|
||||
// to the client immediately.
|
||||
//
|
||||
// Normally, a request will be canceled if the client disconnects
|
||||
// before the response is received from the backend. If explicitly
|
||||
// set to -1, client disconnection will be ignored and the request
|
||||
// will be completed to help facilitate low-latency streaming.
|
||||
FlushInterval caddy.Duration `json:"flush_interval,omitempty"`
|
||||
|
||||
// A list of IP ranges (supports CIDR notation) from which
|
||||
|
@ -757,6 +762,15 @@ func (h *Handler) reverseProxy(rw http.ResponseWriter, req *http.Request, origRe
|
|||
req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))
|
||||
}
|
||||
|
||||
// if FlushInterval is explicitly configured to -1 (i.e. flush continuously to achieve
|
||||
// low-latency streaming), don't let the transport cancel the request if the client
|
||||
// disconnects: user probably wants us to finish sending the data to the upstream
|
||||
// regardless, and we should expect client disconnection in low-latency streaming
|
||||
// scenarios (see issue #4922)
|
||||
if h.FlushInterval == -1 {
|
||||
req = req.WithContext(ignoreClientGoneContext{req.Context(), h.ctx.Done()})
|
||||
}
|
||||
|
||||
// do the round-trip; emit debug log with values we know are
|
||||
// safe, or if there is no error, emit fuller log entry
|
||||
start := time.Now()
|
||||
|
@ -1374,6 +1388,19 @@ type handleResponseContext struct {
|
|||
isFinalized bool
|
||||
}
|
||||
|
||||
// ignoreClientGoneContext is a special context.Context type
|
||||
// intended for use when doing a RoundTrip where you don't
|
||||
// want a client disconnection to cancel the request during
|
||||
// the roundtrip. Set its done field to a Done() channel
|
||||
// of a context that doesn't get canceled when the client
|
||||
// disconnects, such as caddy.Context.Done() instead.
|
||||
type ignoreClientGoneContext struct {
|
||||
context.Context
|
||||
done <-chan struct{}
|
||||
}
|
||||
|
||||
func (c ignoreClientGoneContext) Done() <-chan struct{} { return c.done }
|
||||
|
||||
// proxyHandleResponseContextCtxKey is the context key for the active proxy handler
|
||||
// so that handle_response routes can inherit some config options
|
||||
// from the proxy handler.
|
||||
|
|
Loading…
Reference in a new issue