处理 CORS

配置

从 Socket.IO v3 开始,您需要显式启用跨域资源共享(CORS)。

  1. import { createServer } from "http";
  2. import { Server } from "socket.io";
  3. const httpServer = createServer();
  4. const io = new Server(httpServer, {
  5. cors: {
  6. origin: "https://example.com"
  7. }
  8. });

所有选项都将转发到cors包。可以在此处找到完整的选项列表。

带有 cookie ( withCredentials) 和附加标头的示例:

  1. // server-side
  2. const io = new Server(httpServer, {
  3. cors: {
  4. origin: "https://example.com",
  5. allowedHeaders: ["my-custom-header"],
  6. credentials: true
  7. }
  8. });
  9. // client-side
  10. import { io } from "socket.io-client";
  11. const socket = io("https://api.example.com", {
  12. withCredentials: true,
  13. extraHeaders: {
  14. "my-custom-header": "abcd"
  15. }
  16. });

注意:如果您的 Web 应用程序和服务器不是从同一个端口提供服务,这也适用于 localhost

  1. const io = new Server(httpServer, {
  2. cors: {
  3. origin: "http://localhost:8080"
  4. }
  5. });
  6. httpServer.listen(3000);

您可以使用以下选项禁止所有跨域请求allowRequest option:

  1. const io = new Server(httpServer, {
  2. allowRequest: (req, callback) => {
  3. const noOriginHeader = req.headers.origin === undefined;
  4. callback(null, noOriginHeader);
  5. }
  6. });

故障排除

缺少 CORS 标头“Access-Control-Allow-Origin”

完整的错误信息:

跨域请求被阻止:同源策略不允许读取位于 …/socket.io/?EIO=4&transport=polling&t=NMnp2WI 的远程资源。(原因:缺少 CORS 标头“Access-Control-Allow-Origin”)。

如果您已正确配置您的服务器(见上文),这可能意味着您的浏览器无法访问 Socket.IO 服务器。

以下命令:

  1. curl "https://api.example.com/socket.io/?EIO=4&transport=polling"

应该返回类似:

  1. 0{"sid":"Lbo5JLzTotvW3g2LAAAA","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":20000}

如果不是这种情况,请检查您的服务器是否正在侦听并且实际上可以在给定端口上访问。

如果 CORS 标头“Access-Control-Allow-Origin”为“*”,则不支持凭据

完整的错误信息:

跨域请求被阻止:同源策略不允许读取位于“…/socket.io/?EIO=4&transport=polling&t=NvQfU77”的远程资源。(原因:如果 CORS 标头“Access-Control-Allow-Origin”为“*”,则不支持凭证)

您不能同时设置withCredentialstrueorigin: *,您需要使用特定的来源:

  1. import { createServer } from "http";
  2. import { Server } from "socket.io";
  3. const httpServer = createServer();
  4. const io = new Server(httpServer, {
  5. cors: {
  6. origin: "https://my-frontend.com",
  7. // or with an array of origins
  8. // origin: ["https://my-frontend.com", "https://my-other-frontend.com", "http://localhost:3000"],
  9. credentials: true
  10. }
  11. });

CORS 标头“Access-Control-Allow-Credentials”中预期为“true”

完整的错误信息:

跨域请求被阻止:同源策略不允许读取位于 …/socket.io/?EIO=4&transport=polling&t=NvQny19 的远程资源。(原因:CORS 标头“Access-Control-Allow-Credentials”中预期为“true”)

在这种情况下,在客户端上withCredentials设置为true,但服务器缺少选项credentials中的属性cors 。请参见上面的示例。