如何感知WebSocket子协议被拒绝及服务端如何向客户端传递该拒绝信息?
如何感知WebSocket子协议被拒绝及服务端如何向客户端传递该拒绝信息?
嘿,这个问题我刚好踩过坑!我来给你捋清楚服务端怎么传递拒绝信息,以及客户端怎么精准感知到这个情况~
一、服务端的正确响应方式
你的思路其实是对的,但要注意HTTP响应的格式细节,确保客户端能正确识别。当服务端校验到子协议不合法时,直接返回HTTP 400 Bad Request状态码是最清晰的方式,同时可以在响应体里带上明确的错误描述,让客户端一眼知道问题出在哪。
这里给你调整下服务端代码,确保HTTP响应格式完全合规:
server.on("upgrade", (request, socket, head) => { const clientProtocol = request.headers["sec-websocket-protocol"]; if (clientProtocol !== validProtocol) { // 按照HTTP规范构造响应,注意换行必须是\r\n,响应头和体之间要有空行 socket.end( "HTTP/1.1 400 Bad Request\r\n" + "Connection: close\r\n" + "Content-Type: text/plain\r\n" + "Content-Length: 25\r\n" + "\r\n" + "Subprotocol not supported" ); return; } // 下面写正常的WebSocket握手逻辑(比如用ws库的handleUpgrade) });
按照WebSocket规范,还有一种方式是握手成功但不返回Sec-WebSocket-Protocol响应头,但这种方式客户端只会建立一个没有子协议的连接,完全不知道自己的子协议被拒绝了,体验很差,所以还是返回400的方式更合理。
二、客户端如何感知拒绝
你用的是ReconnectingWebSocket,它基于原生WebSocket封装,所以可以通过监听error和close事件来捕获这个失败:
- 当服务端返回400时,客户端会立刻触发
error事件,随后触发close事件。 - 大部分浏览器会把连接异常关闭的code设为1006,你可以结合这个code来判断是不是子协议被拒绝的问题。
给你写个客户端示例:
this.websocket = new ReconnectingWebSocket(connUrl, [subprotocol]); // 监听错误事件,捕获连接失败的基础信息 this.websocket.onerror = (error) => { console.error("WebSocket连接出错:", error); }; // 监听关闭事件,做更精准的判断 this.websocket.onclose = (event) => { console.log("连接关闭,code:", event.code, "原因:", event.reason); // 1006是异常关闭的默认code,结合我们服务端的逻辑,大概率是子协议不支持 if (event.code === 1006) { alert("服务端不支持你设置的子协议,请检查配置哦"); } };
不过要注意,有些浏览器不会把服务端返回的响应体内容放到event.reason里,这时候你可以根据“连接刚发起就立刻关闭”这个时机,结合业务场景判断是子协议的问题,或者在服务端返回的响应里用更易识别的标识。
备注:内容来源于stack exchange,提问作者Màrius Rak
相关产品推荐
相关产品推荐

