Heroku部署多人俄罗斯方块遇WebSocket握手错误:响应码200
我来给你几个针对性的排查方向,帮你解决这个问题:
修正前端WebSocket连接地址
你当前代码里的new WebSocket(wss://${window.location.hostname}:${window.location.port})存在问题:Heroku部署的应用对外访问时,默认使用HTTPS(对应wss的443端口),不需要显式指定端口——window.location.port在Heroku的域名下会是空值,硬加端口反而会导致连接地址错误。
改成更适配的写法:// 自动适配HTTP/HTTPS对应的ws/wss协议 const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; this.conn = new WebSocket(`${protocol}//${window.location.host}`);(用
window.location.host会自动包含正确的主机和端口,在Heroku下就是不带端口的域名)检查服务器端的WebSocket升级处理逻辑
返回200状态码的核心原因是:服务器把WebSocket的握手请求当成了普通HTTP请求处理,没有正确响应WebSocket的升级请求。比如:- 如果你用
ws库,要确保它和你的HTTP服务器绑定在一起,让它能捕获升级请求:const http = require('http'); const WebSocket = require('ws'); const server = http.createServer(/* 你的HTTP服务逻辑,比如静态文件、API路由 */); const wss = new WebSocket.Server({ server }); - 避免让普通HTTP路由匹配WebSocket的连接路径(比如根路径
/),否则请求会被HTTP路由先拦截并返回200。
- 如果你用
查看Heroku服务器日志定位问题
打开终端运行heroku logs --tail(需要先安装Heroku CLI并登录你的账号),然后触发前端的WebSocket连接请求,观察服务器端的日志:- 看看收到的请求是否包含
Upgrade: websocket和Connection: Upgrade这两个关键头; - 看看服务器是如何响应这个请求的,是否被某个HTTP路由处理并返回了200。
这些日志能帮你快速定位是请求没到达WebSocket处理逻辑,还是处理逻辑本身有问题。
- 看看收到的请求是否包含
确认服务器中间件不会拦截WebSocket请求
如果你用了Express的中间件(比如cors、express-rate-limit等),要确保这些中间件不会拦截WebSocket的升级请求。比如cors中间件需要允许Upgrade和Connection头,或者不对WebSocket路径应用这些中间件。尝试给WebSocket指定专属路径
如果你的WebSocket连接的是根路径/,而服务器正好有根路径的HTTP路由(比如返回前端页面),就会出现请求被HTTP路由先处理的情况。可以改成让WebSocket连接到特定路径,比如/ws:
前端代码改成:const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; this.conn = new WebSocket(`${protocol}//${window.location.host}/ws`);服务器端也对应配置WebSocket监听这个路径:
const wss = new WebSocket.Server({ server, path: '/ws' });
内容的提问来源于stack exchange,提问作者John Ackerman

