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

WebSocket在Safari浏览器无法连接,其余浏览器可正常使用

解决Safari下WebSocket连接失败的问题

首先你的服务端代码存在一处疏漏:createServer未从http模块引入,正确写法如下:

const express = require('express');
const http = require('http'); // 新增引入http模块
const WebSocket = require('ws');
const app = express();
const server = http.createServer(app); // 修正服务器创建逻辑
const server_socket = new WebSocket.Server({ server: server, path: '/ws' });

server_socket.on('connection', function(ws) {
  console.log("client joined");
  ws.on('error', (error) => {console.error('Error:', error);}); // 建议打印具体错误信息,方便排查
  ws.on('close', () => {console.log('client left');});
});

// 补充服务器启动逻辑,示例监听3000端口
server.listen(3000, () => {
  console.log('Server running on port 3000');
});

针对Safari的连接失败问题,核心原因是permessage-deflate扩展的协商不兼容:Safari发送的sec-websocket-extensions仅包含permessage-deflate,缺少其他浏览器带的client_max_window_bits参数,而ws库默认逻辑可能因此拒绝握手。你可以通过以下两种方式适配:

方式一:禁用permessage-deflate扩展

直接关闭压缩扩展,让所有浏览器使用无压缩的WebSocket连接,绕过扩展协商问题:

const server_socket = new WebSocket.Server({ 
  server: server, 
  path: '/ws',
  perMessageDeflate: false // 禁用压缩扩展
});

方式二:调整压缩配置兼容Safari请求

如果需要保留压缩功能,可配置ws库接受不带client_max_window_bits的请求:

const server_socket = new WebSocket.Server({ 
  server: server, 
  path: '/ws',
  perMessageDeflate: {
    clientNoContextTakeover: true,
    serverNoContextTakeover: true,
    clientMaxWindowBits: false // 允许客户端不指定窗口位参数
  }
});

另外需要排查:

  • 服务器防火墙/反向代理(如Nginx)是否拦截了Safari的请求,若使用Nginx需确保WebSocket代理配置正确:
    location /ws {
      proxy_pass http://localhost:3000;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
      proxy_set_header Host $host;
    }
    
  • 确认不存在混合内容拦截(如页面为HTTPS但WebSocket用ws协议,Safari会拦截此类请求)

内容的提问来源于stack exchange,提问作者Ro Anders

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 06:07:41