Express集成SocketIO时源匹配仍出现CORS错误的排查与解决
已解决:参考Phil的评论
解决方案:之前用的浏览器错误提示能力弱,换浏览器后5秒就找到问题
以下为原始问题,保留存档:
我遇到的问题是:当请求源与允许的源仅路径不同时,为何CORS仍会失败?错误信息如下:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:3030/socket.io/?EIO=4&transport=polling&t=OhAxRtW. (Reason: CORS header ‘Access-Control-Allow-Origin’ does not match ‘http://localhost:3030’).
根据CORS的定义:
跨源资源共享(CORS)是一种基于HTTP头的机制,允许服务器指定浏览器可以加载资源的源(域名、协议或端口)。
在我收到的错误信息中:
- 两者协议相同:
http - 两者域名相同:
localhost - 两者端口相同:
3030
既然协议、域名和端口都匹配,为何会出现这个错误?
直接对比:
http://localhost:3030/socket.io/?EIO=4&transport=polling&t=OhAxRtW http://localhost:3030
CORS的源判断不应该包含路径,那为何会出现不匹配的情况?
我的代码如下:
// server import express from 'express'; import http from 'http'; import { Server } from 'socket.io'; const app = express(); const httpServer = http.createServer(app); const io = new Server(httpServer, { // @ts-expect-error cors: { origin: "http://localhost:3030" } }); const port = 3030; io.on('connection', (socket) => { console.log('A user connected'); // Handle socket events here socket.on('data', (payload) => { console.log(payload); }); socket.on('disconnect', () => { console.log('User disconnected'); }); }); httpServer.listen(port, () => { console.log(`Server is running on port ${port}`); });
// client 'use client'; import React, { useEffect, useState } from 'react'; import io, { Socket } from 'socket.io-client'; export const SocketTest = (): JSX.Element => { const [socket, setSocket] = useState<Socket | null>(null); useEffect(() => { const skt = io('ws://localhost:3030'); setSocket(skt); skt.on('connect', () => { console.log('Connected to Socket.io'); }); // Handle socket events here return () => { skt.disconnect(); }; }, []); return ( <div> <h1>Socket.io Demo</h1> <button onClick={() => { if (socket !== null) { console.log('socket emit'); socket.emit("data", { message: "client data" }); } }} >clicky</button> </div> ); } export default SocketTest;
注意:如果将cors: { origin: ...改为通配符,一切正常,但我不想在生产代码中使用通配符。
cors: { origin: "*" // works }
根据Socket.io的排查建议,我用curl测试,结果正常,即使CORS请求失败时也是如此:
我的curl命令及结果:
$ curl "http://localhost:3030/socket.io/?EIO=4&transport=polling" 0{"sid":"g4HqqSTX0oXDcEJpAAAJ","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":20000,"maxPayload":1000000}%
内容的提问来源于stack exchange,提问作者Steverino
相关产品推荐
相关产品推荐

