Docker中Node.js WebSocket连接报错:RSV1保留位被置1问题排查
问题场景
我在Docker容器中运行Node.js服务器,通过浏览器WebSocket连接时,建立后立即报错:
WebSocket connection to 'wss://domain/api/websockets' failed: One or more reserved bits are on: reserved1 = 1, reserved2 = 0, reserved3 = 0.
进入容器用wscat测试连接:
wscat --header "Cookie:connect.sid=session-key" -c ws://127.0.0.1:5200/api/websockets
依然收到报错:
error: Invalid WebSocket frame: RSV1 must be clear
注:初始连接能收到服务器发送的有效数据包,但不久后会因上述错误断开。
服务端代码
import WebSocket, { WebSocketServer } from "ws"; import { Server } from "http"; import { sessionParser } from "../passport"; import { User } from "../../share-types"; import { events, EventsList } from "./events"; export default async (server: Server) => { const wsServer = new WebSocketServer({ noServer: true, path: '/api/websockets', }); server.on('upgrade', (request: Express.Request, socket, head) => { sessionParser(request, {}, () => { const user: User = request.session?.passport?.user; if (!user?.ID) return socket.destroy(); wsServer.handleUpgrade(request as any, socket, head, (ws) => { wsServer.emit('connection', ws, request, user); }); }) }); wsServer.on('connection', function (socket: WebSocket, request: Express.Request, user: User) { socket.on('error', console.error); socket.on('message', function (message) { try { message = JSON.parse(message.toString()); events.emit(EventsList.NEW_WEB_SOCKET_MESSAGE, { user, message }); } catch { } }); }); return wsServer; };
WS包版本:"ws": "^8.16.0"
可能的原因分析
1. 数据压缩配置冲突
RSV1位通常与WebSocket的permessage-deflate扩展(数据压缩)绑定。如果客户端与服务器的压缩协商不一致——比如服务器默认启用压缩,但客户端/代理不支持,就会导致帧的RSV1位被错误标记。
ws v8.x版本默认开启permessage-deflate,可尝试显式关闭压缩验证:
const wsServer = new WebSocketServer({ noServer: true, path: '/api/websockets', perMessageDeflate: false // 关闭数据压缩 });
2. 反向代理的WebSocket处理异常
若服务前端有Nginx、Traefik等反向代理,代理可能在转发WebSocket帧时篡改了RSV位。比如代理自行启用压缩,但未正确传递WebSocket的扩展协商信息,导致服务器与客户端的压缩配置不匹配。
检查代理配置,确保WebSocket升级请求被正确转发,且未对WebSocket路径启用额外压缩。以Nginx为例,需包含:
proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_cache_bypass $http_upgrade;
3. 中间件干扰WebSocket帧
检查是否有HTTP中间件在upgrade事件处理前修改了socket状态,比如部分中间件会意外处理WebSocket升级请求,导致帧结构被篡改。
4. 版本兼容问题
虽然使用的是ws v8.16.0(较新版本),仍可尝试升级至最新版,排查是否存在已知的RSV位相关bug。
内容的提问来源于stack exchange,提问作者ABE

