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

使用Socket.io时仅断开重连出现CORS错误的原因排查

Socket.io 重连时CORS错误排查与解决

问题现象

前端先启动、后启动服务器时,Socket.io连接可正常建立;但断开前端连接后重新启动,会触发CORS错误:

从源 'http://localhost:3000' 访问 'http://localhost:3001/socket.io/?EIO=4&transport=polling&t=pypdmqlh' 的XMLHttpRequest被CORS策略阻止:预检请求的响应未通过访问控制检查:它没有HTTP ok状态。

当前配置

Socket.io的CORS配置

export const registerSocketServer = (server: HttpServer) => {
  const io = new Server<
    ClientToServerEvents,
    ServerToClientEvents,
    InterServerEvents,
    SocketData
  >(server, {
    cors: {
      //   origin: true,
      origin: [`${process.env.FRONTEND_URL}`, "*"],

      methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
      credentials: true,
      //   allowedHeaders: "*",
      allowedHeaders: [
        "Content-Type",
        "AccessKey",
        "st-auth-mode",
        "rid",
        "x-file-name",
        "x-start-byte",
        "x-end-byte",
        "x-total-size",
        "content-type",
        "Access-Control-Max-Age",
        "Access-Control-Allow-Origin",
        "Access-Control-Allow-Methods",
        "Access-Control-Allow-Headers",
        ...getAllCORSHeaders(),
      ],
    },

    // allow max 10mb file
    maxHttpBufferSize: 1e7,
  });

Express的CORS配置(server.js)

app.use(
  cors({
    origin: [`${process.env.FRONTEND_URL}`, "*"],
    // // origin: "*", //allow all
    // // allowedHeaders: ["content-type", ...getAllCORSHeaders()],
    allowedHeaders: [
      "Content-Type",
      "AccessKey",
      "st-auth-mode",
      "rid",
      "x-file-name",
      "x-start-byte",
      "x-end-byte",
      "x-total-size",
      "content-type",
      "Access-Control-Max-Age",
      "Access-Control-Allow-Origin",
      "Access-Control-Allow-Methods",
      "Access-Control-Allow-Headers",
      ...getAllCORSHeaders(),
    ],
    methods: ["GET", "POST", "PUT", "DELETE"],
    credentials: true, // Ensure credentials are allowed
  }),
);

错误分析

  1. 凭证与通配符冲突:当credentials: true时,CORS规范禁止使用origin: "*",必须指定具体域名,否则浏览器会拒绝接受响应。
  2. 预检请求未被正确处理:Express的CORS配置中未包含OPTIONS方法,而预检请求依赖该方法获取服务器允许的跨域规则,导致请求返回非200状态码。
  3. 冗余响应头配置:allowedHeaders中包含Access-Control-*系列头,这些是服务器响应时返回的头,不是客户端请求需要携带的头,属于无效配置。

解决方法

1. 修正Origin配置

移除通配符*,仅保留具体的前端域名,两处配置保持一致:

// Socket.io配置
origin: `${process.env.FRONTEND_URL}`,
// Express CORS配置
origin: `${process.env.FRONTEND_URL}`,

2. 添加OPTIONS方法到Express配置

确保Express能处理预检请求:

methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],

3. 简化AllowedHeaders配置

移除冗余的Access-Control-*头,仅保留客户端实际需要发送的请求头:

// Socket.io配置
allowedHeaders: [
  "Content-Type",
  "AccessKey",
  "st-auth-mode",
  "rid",
  "x-file-name",
  "x-start-byte",
  "x-end-byte",
  "x-total-size",
  ...getAllCORSHeaders(),
],
// Express CORS配置
allowedHeaders: [
  "Content-Type",
  "AccessKey",
  "st-auth-mode",
  "rid",
  "x-file-name",
  "x-start-byte",
  "x-end-byte",
  "x-total-size",
  ...getAllCORSHeaders(),
],

4. 重启服务测试

修改配置后重启服务器,断开前端连接再重新启动,确认预检请求返回200 OK,CORS错误消失。

内容的提问来源于stack exchange,提问作者Saifullah Rahman

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 11:44:52