使用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 }), );
错误分析
- 凭证与通配符冲突:当
credentials: true时,CORS规范禁止使用origin: "*",必须指定具体域名,否则浏览器会拒绝接受响应。 - 预检请求未被正确处理:Express的CORS配置中未包含
OPTIONS方法,而预检请求依赖该方法获取服务器允许的跨域规则,导致请求返回非200状态码。 - 冗余响应头配置: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
相关产品推荐
相关产品推荐

