aboutsummaryrefslogtreecommitdiffhomepage
path: root/modules
diff options
context:
space:
mode:
authorWeidiDeng <[email protected]>2024-04-26 23:09:18 +0800
committerGitHub <[email protected]>2024-04-26 09:09:18 -0600
commit1b9042bcdd03b4edea8447355f970e1c5aff8c10 (patch)
tree9d45812da2d43d16759c5cf7f3cfbf065f3dfa3b /modules
parent4d6370bf92de163a53aec9081c5d5ae6614597a0 (diff)
downloadcaddy-1b9042bcdd03b4edea8447355f970e1c5aff8c10.tar.gz
caddy-1b9042bcdd03b4edea8447355f970e1c5aff8c10.zip
reverseproxy: handle buffered data during hijack (#6274)
Diffstat (limited to 'modules')
-rw-r--r--modules/caddyhttp/responsewriter.go2
-rw-r--r--modules/caddyhttp/reverseproxy/streaming.go11
2 files changed, 13 insertions, 0 deletions
diff --git a/modules/caddyhttp/responsewriter.go b/modules/caddyhttp/responsewriter.go
index 12627d45c..d51d37cb2 100644
--- a/modules/caddyhttp/responsewriter.go
+++ b/modules/caddyhttp/responsewriter.go
@@ -263,6 +263,8 @@ func (rr *responseRecorder) Hijack() (net.Conn, *bufio.ReadWriter, error) {
conn.(*hijackedConn).updateReadSize(buffered)
data, _ := brw.Peek(buffered)
brw.Reader.Reset(io.MultiReader(bytes.NewReader(data), conn))
+ // peek to make buffered data appear, as Reset will make it 0
+ _, _ = brw.Peek(buffered)
} else {
brw.Reader.Reset(conn)
}
diff --git a/modules/caddyhttp/reverseproxy/streaming.go b/modules/caddyhttp/reverseproxy/streaming.go
index 6d8990575..a696ac7fb 100644
--- a/modules/caddyhttp/reverseproxy/streaming.go
+++ b/modules/caddyhttp/reverseproxy/streaming.go
@@ -101,6 +101,17 @@ func (h *Handler) handleUpgradeResponse(logger *zap.Logger, wg *sync.WaitGroup,
return
}
+ // There may be buffered data in the *bufio.Reader
+ // see: https://github.com/caddyserver/caddy/issues/6273
+ if buffered := brw.Reader.Buffered(); buffered > 0 {
+ data, _ := brw.Peek(buffered)
+ _, err := backConn.Write(data)
+ if err != nil {
+ logger.Debug("backConn write failed", zap.Error(err))
+ return
+ }
+ }
+
// Ensure the hijacked client connection, and the new connection established
// with the backend, are both closed in the event of a server shutdown. This
// is done by registering them. We also try to gracefully close connections