@@ -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