使用apollo-server-express、socket.io时客户端连接触发CORS报错
问题根因
applyMiddleware里配置的CORS仅对Apollo的/graphql接口生效,管不到Socket.IO挂载的/socket.io路径,这是跨域报错的直接原因。- Socket.IO v4 不会自动继承express的CORS配置,必须在初始化io实例时单独传入CORS参数。
- 你虽然引入了
cors依赖,但没有给express实例注册全局CORS中间件,/login、/callback这类普通接口本身也存在跨域隐患;另外客户端初始化socket时没开凭证携带,就算跨域问题解决,后续也会读不到session里存的socketId。
修复方案
1. 服务端给Socket.IO加CORS配置
把原来初始化io的代码替换成下面的内容:
const io = socketio(httpServer, { cors: { origin: "http://localhost:3000", methods: ["GET", "POST"], credentials: true } });
2. 给express注册全局CORS中间件
在配置路由、Apollo中间件之前,先挂载cors:
// 放在app.use(express.json())之前 app.use(cors({ origin: "http://localhost:3000", credentials: true }));
全局配了CORS之后,server.applyMiddleware里单独传的cors选项可以删掉,避免重复配置冲突。
3. 客户端修改socket初始化参数
加上withCredentials: true,保证跨域请求携带cookie,session逻辑才能正常运行:
import io from "socket.io-client"; const API_URL = "http://127.0.0.1:4000"; const socket = io(API_URL, { withCredentials: true });
额外注意
你现在session的secret是每次服务启动随机生成的,重启服务后所有旧session都会失效,开发阶段无影响,上线前记得换成固定的环境变量值。
改完重启服务、刷新前端,Socket.IO的跨域报错就会消失,Twitter授权回调后也能正常把消息推到前端窗口。
内容的提问来源于stack exchange,提问作者j-mars
相关产品推荐
相关产品推荐

