在使用React的浏览器中,Socket.IO的 WebSocket握手过程中发生错误,返回了意外的响应码404
我正在通过一个API网关连接到Socket.IO服务器(这是Kong与 Cloudflare的混合产品,我们使用它但并不拥有,无法更改其配置)从一个React应用发起。连接在浏览器中失败,显示为:
Error during WebSocket handshake: Unexpected response code: 404
React代码:
我需要传递两个认证令牌(必填),auth 属性中的认证令牌用于在WebSocket使用中的内部身份验证。Authorization 用于调用API网关。它是必填的,后端需要收到一个令牌以进行身份验证。
const socket = io('https://my-gateway.example.com', {
path: '/api/socket.io/',
transports: ['websocket'],
auth: { token: '...' },
extraHeaders: {
Authorization: 'Bearer <Token>',
'x-upstream-env': 'stage',
},
});
浏览器调用:
wss://my-gateway.example.com/api/socket.io/?EIO=4&transport=websocket
自定义头信息无法通过浏览器的WebSocket连接发送,这是我所了解的。
我们也不想用Node.js构建一个代理来调用后端。
我也尝试把传输模式保持为轮询(polling)。它仍然失败,x-upstream-env也很重要,用来确定环境,因此我们不能移除该属性。
如果有人能提供帮助就太好了!
谢谢
解决方案
根本原因是浏览器不能在WebSocket连接上设置自定义头信息,这是一个平台限制,不是Socket.IO的 bug。使用transports: ['websocket'] 时,你的extraHeaders(Authorization和 x-upstream-env)会被静默丢弃,因此握手在没有它们的情况下到达Kong。Kong的路由可以基于头信息进行匹配,当没有路由匹配时就返回404,这很可能就是你遇到的错误。路径不匹配是另一个常见原因:如果Kong剥离了 /api前缀,上游服务器的Socket.IO路径必须设置为 /socket.io/。
首先,在浏览器之外进行诊断,因为curl会发送这些头信息:
curl -i "https://my-gateway.example.com/api/socket.io/?EIO=4&transport=polling" \
-H "Authorization: Bearer <token>" \
-H "x-upstream-env: stage"
如果这返回 0{"sid":...} 路由工作且问题是浏览器头信息的限制。如果它也返回404,那就是路由/路径问题,无法通过客户端改动来解决。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。