From 34af75aaa175ae907ad21f3a08eaba6f97780dcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=20Luis=20Monta=C3=B1es=20Ojados?= Date: Tue, 27 Jan 2026 13:32:45 +0100 Subject: [PATCH] Fix panic in WebSocket handling by manually writing headers instead of using r.Write --- cmd/server/main.go | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/cmd/server/main.go b/cmd/server/main.go index 7b5a371..32991cc 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -180,10 +180,21 @@ func startHttpProxy(port string) { } defer clientConn.Close() - // Reconstruct request line and headers to send to backend - // We can use r.Write but it writes to the channel - if err := r.Write(ch); err != nil { - log.Printf("Error writing websocket request to backend: %v", err) + // Manual Request writing to avoid touching Body after Hijack/Panic + // Request Line + reqLine := fmt.Sprintf("%s %s %s\r\n", r.Method, r.RequestURI, r.Proto) + if _, err := io.WriteString(ch, reqLine); err != nil { + log.Printf("Error writing websocket request line: %v", err) + return + } + // Headers + if err := r.Header.Write(ch); err != nil { + log.Printf("Error writing websocket headers: %v", err) + return + } + // End of headers + if _, err := io.WriteString(ch, "\r\n"); err != nil { + log.Printf("Error writing websocket header terminator: %v", err) return } @@ -192,7 +203,12 @@ func startHttpProxy(port string) { // Copy existing buffer from hijack + future reads -> backend go func() { - defer wg.Done() + defer func() { + if r := recover(); r != nil { + log.Printf("Recovered from panic in WS writer: %v", r) + } + wg.Done() + }() if bufrw.Reader.Buffered() > 0 { io.CopyN(ch, bufrw, int64(bufrw.Reader.Buffered())) } @@ -201,7 +217,12 @@ func startHttpProxy(port string) { // Backend -> Browser go func() { - defer wg.Done() + defer func() { + if r := recover(); r != nil { + log.Printf("Recovered from panic in WS reader: %v", r) + } + wg.Done() + }() io.Copy(clientConn, ch) }()