diff --git a/transport/vmess/websocket.go b/transport/vmess/websocket.go index 772c6fef..31f09aac 100644 --- a/transport/vmess/websocket.go +++ b/transport/vmess/websocket.go @@ -555,7 +555,7 @@ func StreamUpgradedWebsocketConn(w http.ResponseWriter, r *http.Request) (net.Co w.Header().Set("Sec-Websocket-Accept", getSecAccept(r.Header.Get("Sec-WebSocket-Key"))) } w.WriteHeader(http.StatusSwitchingProtocols) - if flusher, isFlusher := w.(interface{ FlushError() error }); isFlusher { + if flusher, isFlusher := w.(interface{ FlushError() error }); isFlusher && writeHeaderShouldFlush { err = flusher.FlushError() if err != nil { return nil, fmt.Errorf("flush response: %w", err) diff --git a/transport/vmess/websocket_go120.go b/transport/vmess/websocket_go120.go new file mode 100644 index 00000000..0b9ff5e3 --- /dev/null +++ b/transport/vmess/websocket_go120.go @@ -0,0 +1,7 @@ +//go:build !go1.21 + +package vmess + +// Golang1.20's net.http Flush will mistakenly call w.WriteHeader(StatusOK) internally after w.WriteHeader(http.StatusSwitchingProtocols) +// https://github.com/golang/go/issues/59564 +const writeHeaderShouldFlush = false diff --git a/transport/vmess/websocket_go121.go b/transport/vmess/websocket_go121.go new file mode 100644 index 00000000..9419cd50 --- /dev/null +++ b/transport/vmess/websocket_go121.go @@ -0,0 +1,5 @@ +//go:build go1.21 + +package vmess + +const writeHeaderShouldFlush = true