You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何感知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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.16 11:55:26