aboutsummaryrefslogtreecommitdiffhomepage
path: root/modules
diff options
context:
space:
mode:
authorMatthew Holt <[email protected]>2024-04-22 15:22:50 -0600
committerMatthew Holt <[email protected]>2024-04-22 15:22:50 -0600
commitd93e027e01905406671ed8df295d5e48d16645c2 (patch)
treeadd0a3a58570baaf36d2a647b7402cc5df72808c /modules
parent613d544a4775b831595f223028fee76b980aa003 (diff)
downloadcaddy-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.
Diffstat (limited to 'modules')
-rw-r--r--modules/caddyhttp/reverseproxy/reverseproxy.go9
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 {