diff options
author | Matthew Holt <[email protected]> | 2024-04-22 15:22:50 -0600 |
---|---|---|
committer | Matthew Holt <[email protected]> | 2024-04-22 15:22:50 -0600 |
commit | d93e027e01905406671ed8df295d5e48d16645c2 (patch) | |
tree | add0a3a58570baaf36d2a647b7402cc5df72808c | |
parent | 613d544a4775b831595f223028fee76b980aa003 (diff) | |
download | caddy-d93e027e01905406671ed8df295d5e48d16645c2.tar.gz caddy-d93e027e01905406671ed8df295d5e48d16645c2.zip |
reverseproxy: Reuse buffered request body even if partially drained
Previous commit only works when the backends don't read any of the body first.
-rw-r--r-- | modules/caddyhttp/reverseproxy/reverseproxy.go | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/modules/caddyhttp/reverseproxy/reverseproxy.go b/modules/caddyhttp/reverseproxy/reverseproxy.go index 048539e93..980e259c9 100644 --- a/modules/caddyhttp/reverseproxy/reverseproxy.go +++ b/modules/caddyhttp/reverseproxy/reverseproxy.go @@ -439,6 +439,15 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyht var proxyErr error var retries int for { + // if the request body was buffered (and only the entire body, hence no body + // set to read from after the buffer), make reading from the body idempotent + // and reusable, so if a backend partially or fully reads the body but then + // produces an error, the request can be repeated to the next backend with + // the full body (retries should only happen for idempotent requests) (see #6259) + if reqBodyBuf, ok := r.Body.(bodyReadCloser); ok && reqBodyBuf.body == nil { + r.Body = io.NopCloser(bytes.NewReader(reqBodyBuf.buf.Bytes())) + } + var done bool done, proxyErr = h.proxyLoopIteration(clonedReq, r, w, proxyErr, start, retries, repl, reqHeader, reqHost, next) if done { |