Skip to content

Commit e199e15

Browse files
authored
Merge pull request #8311 from bcxpro/8276-http2-settings-frame-issue
fix: ensure reverse proxy buffered data is forwarded during HTTP/2 protocol upgrades
2 parents 95a2b90 + 8dee3bf commit e199e15

File tree

1 file changed

+22
-5
lines changed

1 file changed

+22
-5
lines changed

src/go/wsl-helper/pkg/dockerproxy/util/reverse_proxy.go

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,13 +107,13 @@ func (proxy *ReverseProxy) forwardRequest(w http.ResponseWriter, r *http.Request
107107
}
108108

109109
// Read the response from the backend
110-
backendResponse, err := http.ReadResponse(bufio.NewReader(backendConn), newReq)
110+
bufferedReader := bufio.NewReader(backendConn)
111+
backendResponse, err := http.ReadResponse(bufferedReader, newReq)
111112
if err != nil {
112113
proxy.sendError(w, "failed to read the response from the backend: "+err.Error(), http.StatusBadGateway)
113114
return
114115
}
115116
defer backendResponse.Body.Close()
116-
117117
// ModifyResponse function
118118
// Allows post-processing of the backend response
119119
if proxy.ModifyResponse != nil {
@@ -137,7 +137,16 @@ func (proxy *ReverseProxy) forwardRequest(w http.ResponseWriter, r *http.Request
137137

138138
// Check if the response has a status code of 101 (Switching Protocols)
139139
if backendResponse.StatusCode == http.StatusSwitchingProtocols {
140-
proxy.handleUpgradedConnection(w, backendConn)
140+
// When reading the response, the buffered reader may have consumed part of the body
141+
// beyond the headers. We need to recover these overread bytes and ensure they are
142+
// sent to the client immediately after hijacking the connection.
143+
bufferedBytesLen := bufferedReader.Buffered()
144+
pendingResponseBytes, err := bufferedReader.Peek(bufferedBytesLen)
145+
if err != nil {
146+
proxy.logf("failed to peek for buffered bytes: %v", err)
147+
return
148+
}
149+
proxy.handleUpgradedConnection(w, backendConn, pendingResponseBytes)
141150
return
142151
}
143152

@@ -156,9 +165,9 @@ func (proxy *ReverseProxy) forwardRequest(w http.ResponseWriter, r *http.Request
156165
//
157166
// This method:
158167
// - Hijacks the existing connection
159-
// - Manages buffered data
168+
// - Handling any buffered data that was overread during the initial response parsing
160169
// - Enables bidirectional communication after protocol upgrade
161-
func (proxy *ReverseProxy) handleUpgradedConnection(w http.ResponseWriter, backendConn net.Conn) {
170+
func (proxy *ReverseProxy) handleUpgradedConnection(w http.ResponseWriter, backendConn net.Conn, pendingResponseBytes []byte) {
162171
// Cast writer to safely hijack the connection
163172
hijacker, ok := w.(http.Hijacker)
164173
if !ok {
@@ -201,6 +210,14 @@ func (proxy *ReverseProxy) handleUpgradedConnection(w http.ResponseWriter, backe
201210
}
202211
}
203212

213+
// After hijacking the connection, send any pending bytes that were overread by the buffered reader
214+
// during the initial response parsing. This ensures no data is lost during the protocol upgrade.
215+
_, err = clientConn.Write(pendingResponseBytes)
216+
if err != nil {
217+
proxy.logf("failed to write pending response data the client: %v", err)
218+
return
219+
}
220+
204221
// Cast backend and client connections to HalfReadWriteCloser
205222
var halfCloserBackendConn HalfReadWriteCloser
206223
var halfCloserClientConn HalfReadWriteCloser

0 commit comments

Comments
 (0)