使用Boost库时WebSocket握手报错Connection字段缺少upgrade token如何解决
问题原因
这个报错的本质是你用Boost.Beast实现的WebSocket服务端,收到的握手请求不符合WebSocket协议规范:HTTP头的Connection字段没有携带upgrade令牌。常见触发场景有3种:
- 前端JS代码里的
WEB_SOCKET_URL配置错误,比如误填了部署静态页面的node.js HTTP服务端口,没有指向Boost WebSocket服务的监听端口,或是协议写错为http而非ws,导致发出去的不是标准WebSocket握手请求。 - 如果你用node.js做了反向代理把前端的WebSocket请求转发到Boost服务,代理配置没有开启WebSocket支持,转发时丢失了Upgrade、Connection等必要的协议头。
- 你的Boost服务端逻辑有缺陷:直接对所有进入的TCP连接都执行WebSocket握手逻辑,没有提前区分普通HTTP请求和WebSocket握手请求,普通HTTP请求进入握手流程就会触发这个报错。
修复方案
你可以按照以下顺序排查修复:
- 校验客户端请求配置
确认JS代码中WEB_SOCKET_URL格式正确,示例:ws://127.0.0.1:8080,其中端口号必须是Boost WebSocket服务的监听端口,不能和node.js静态页面服务的端口混淆。 - 修正node.js代理配置(如果使用了代理)
如果你通过node.js转发WebSocket请求,需要在代理规则中开启WebSocket支持,以http-proxy-middleware为例:
const { createProxyMiddleware } = require('http-proxy-middleware'); const wsProxy = createProxyMiddleware('/websocket-path', { target: 'http://127.0.0.1:<Boost服务端口>', ws: true, // 必须开启,支持WebSocket代理 changeOrigin: true, });
- 完善Boost服务端的请求判断逻辑
不要直接把TCP连接交给WebSocket模块处理,先读取HTTP请求头,判断是WebSocket握手请求后再执行握手逻辑,参考代码示例:
// 监听接收TCP连接后,先交给HTTP会话处理 void listener::on_accept(beast::error_code ec, tcp::socket socket) { if (!ec) { std::make_shared<http_session>(std::move(socket))->run(); } do_accept(); } // HTTP会话中判断请求类型 void http_session::on_read(beast::error_code ec, std::size_t bytes_transferred) { boost::ignore_unused(bytes_transferred); if (ec == http::error::end_of_stream) { return do_close(); } if (ec) { return fail(ec, "read"); } // 仅WebSocket握手请求移交WebSocket模块处理 if (websocket::is_upgrade(req_)) { std::make_shared<session>(std::move(socket_))->run(std::move(req_)); return; } // 普通HTTP请求返回400或对应响应 send_response(http::response<http::string_body>{http::status::bad_request, req_.version()}); }
- 调试验证
打开浏览器开发者工具的「网络」面板,筛选「WS」类型请求,查看握手请求的请求头,确认存在Connection: Upgrade和Upgrade: websocket两个字段,确认请求合法。
内容的提问来源于stack exchange,提问作者Taki
相关产品推荐
相关产品推荐

