部署在Heroku的WebSocket Server初始化失败,客户端报404错误求助
问题背景
项目原采用Server Sent Events推送交易状态,因Firefox下表现不稳定改用WebSocket。本地开发环境连接正常,但部署到Heroku后客户端连接被拦截,Heroku日志显示路径/api/v1/ws返回404状态码。已通过heroku features:enable http-session-affinity -a your-app-name配置会话亲和性,问题仍未解决。
核心问题分析
代码存在两个关键错误导致WebSocket路由无法被Heroku正确识别:
URL匹配缺失开头斜杠
在自定义的server.on('upgrade')事件处理中,判断条件request.url === 'api/v1/ws'与实际请求URL/api/v1/ws(带开头斜杠)不匹配,导致WebSocket握手被直接拒绝,请求最终落入兜底的404路由。服务器启动方式错误
代码中创建了HTTP服务器实例server用于挂载WebSocket,但最终调用app.listen()启动服务——这会创建一个全新的独立HTTP服务器,导致之前绑定在server上的WebSocket配置完全失效。
修复方案
1. 修正URL匹配逻辑
将upgrade事件中的URL判断改为带开头斜杠的正确路径:
// 原错误代码 if (request.headers.upgrade === 'websocket' && request.url === 'api/v1/ws') { // 修改后代码 if (request.headers.upgrade === 'websocket' && request.url === '/api/v1/ws') {
2. 使用正确的服务器启动方法
替换app.listen()为server.listen(),确保WebSocket绑定的服务器被正确启动:
// 原错误代码 app.listen(port, () => { console.log(`Server is listening on port ${port}`); }); // 修改后代码 server.listen(port, () => { console.log(`Server is listening on port ${port}`); });
3. 优化WebSocket路由配置(可选)
由于ws库通过new WebSocketServer({ server })绑定服务器时,会自动处理upgrade事件,自定义的upgrade逻辑属于冗余代码,还可能引发冲突。推荐直接在创建WebSocketServer时指定路径,替代手动判断:
// 创建WebSocketServer时指定路径,无需自定义upgrade事件 const wss: WebSocketServer = new WebSocketServer({ server, path: '/api/v1/ws' });
此配置会自动拦截/api/v1/ws路径的WebSocket请求,其他路径则正常走Express路由逻辑。
内容的提问来源于stack exchange,提问作者code46

