简体   繁体   English

Socket.io 给出 CORS 错误,即使我在服务器上允许 cors

[英]Socket.io gives CORS error even if I allowed cors it on server

My node server and client are running on different ports(3001,5347 respectively).我的节点服务器和客户端在不同的端口(分别为 3001、5347)上运行。 On client I had used,在我用过的客户端上,

var socket = io('http://127.0.0.1:3001');

On server I tried all of following one by one在服务器上,我一一尝试了以下所有内容

    1) io.set('origins', '*:*');
    2) io.set('origins', 'http://127.0.0.1:5347');
    3) io.set('origins', '*');
    4) io.set('origins', '127.0.0.1:5347');

But I'm getting following error:但我收到以下错误:

XMLHttpRequest cannot load http://127.0.0.1:3001/socket.io/?EIO=3&transport=polling&t=1456799439856-4590 . XMLHttpRequest 无法加载http://127.0.0.1:3001/socket.io/?EIO=3&transport=polling&t=1456799439856-4590 A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true.当凭据标志为真时,不能在“Access-Control-Allow-Origin”header 中使用通配符“*”。 Origin 'null' is therefore not allowed access.因此不允许访问 Origin 'null'。

Note: I'm using express on server and I'm already using cors middleware in following way:注意:我在服务器上使用 express 并且我已经通过以下方式使用 cors 中间件:

app.use(cors());

Where app and cors are instances of express and cors respectively.其中app和cors分别是express和cors的实例。

If running Express as follows:如果按如下方式运行 Express:

var app = express();
var server = app.listen(3000);

So to start socket.io, we can do the following:因此,要启动 socket.io,我们可以执行以下操作:

var io = require('socket.io').listen(server);

The problem was because of following code:问题是由于以下代码:

var http = require('http').Server(app);
var io = require('socket.io')(http);

The server object passed to socket.io was not the same as the server object I'm listening on.传递给 socket.io 的服务器对象与我正在侦听的服务器对象不同。

The accepted answer is outdated接受的答案已过时

According to the official docs, you can add it to an existing http Server https://socket.io/docs/server-initialization/#Attached-to-an-existing-HTTP-server根据官方文档,您可以将其添加到现有的 http 服务器https://socket.io/docs/server-initialization/#Attached-to-an-existing-HTTP-server

const server = require('http').createServer();
const options = { /* ... */ };
const io = require('socket.io')(server, options);
io.on('connection', socket => { /* ... */ });
server.listen(3000);

to enable cors using this options object seemed to do the trick使用此选项对象启用 cors 似乎可以解决问题

options={
 cors:true,
 origins:["http://127.0.0.1:5347"],
}

Back in 2014 they added support for method as part of the origin parameter:早在 2014 年,他们就添加了对方法的支持作为 origin 参数的一部分:

let socket = io(web_server, {
    cors: { 
        origin: function(origin, fn) {
            if(origin == 'http://example.com')
                return fn(null, origin);
            return fn('Error Invalid domain');
        } 
    },
});

You can validate the domain with an external call, a database or an array...您可以使用外部调用、数据库或数组来验证域...

The function fn execute the following logic:函数 fn 执行以下逻辑:

function fn(err2, origin) {
    if (err2 || !origin) {
        next(err2);
    } else {
        corsOptions.origin = origin;
        cors(corsOptions, req, res, next);
    }
}

Ability to dynamically define CORS headers https://github.com/socketio/socket.io/issues/1772能够动态定义 CORS 标头https://github.com/socketio/socket.io/issues/1772

While migrating to socket.io v3.0+ , there is a migration change on how to setup CORS.在迁移到socket.io v3.0+ 时,关于如何设置 CORS 的迁移发生了变化。 https://socket.io/docs/v3/migrating-from-2-x-to-3-0/index.html#Configuration https://socket.io/docs/v3/migrating-from-2-x-to-3-0/index.html#Configuration

Before socket.io v3.0:在 socket.io v3.0 之前:

const io = require("socket.io")(httpServer, {
  origins: ["https://example.com"],

  // optional, useful for custom headers
  handlePreflightRequest: (req, res) => {
    res.writeHead(200, {
      "Access-Control-Allow-Origin": "https://example.com",
      "Access-Control-Allow-Methods": "GET,POST",
      "Access-Control-Allow-Headers": "my-custom-header",
      "Access-Control-Allow-Credentials": true
    });
    res.end();
  }
});

After socket.io v3.0:在 socket.io v3.0 之后:

const io = require("socket.io")(httpServer, {
  cors: {
    origin: "https://example.com",
    methods: ["GET", "POST"],
    allowedHeaders: ["my-custom-header"],
    credentials: true
  }
});

The function is supported on the origin parameter in v3.0 of socket.io socket.io v3.0中的origin参数支持该函数

Note that you can use cors() with app before you pass app into require('http'), which is then passed into socket.io.请注意,在将 app 传递到 require('http') 之前,您可以将 cors() 与 app 一起使用,然后将其传递到 socket.io。 In this order.按照这个顺序。 This should work too.这也应该有效。

const app = express();

app.use(cors());
const http = require('http').Server(app);
const io = require('socket.io')(http);

Hope it helps.希望能帮助到你。

If you get socket.io app working on Chrome, Safari and other browsers but you still encounter CORS issues in Firefox, and you are using a self-signed certificate, then the problem is that Firefox does not accept self-signed certificates by default, and you have to add an exception by going to Firefox's Preferences > Certificates > View Certificates > Add Exception.如果您在 Chrome、Safari 和其他浏览器上运行 socket.io 应用程序,但在 Firefox 中仍然遇到 CORS 问题,并且您使用的是自签名证书,那么问题在于 Firefox 默认不接受自签名证书,并且您必须通过转到 Firefox 的首选项 > 证书 > 查看证书 > 添加例外来添加例外。

If you don't do this, then Firefox shows the error you posted which is misleading, but deep within its Developer Tools, you will find this error: MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT.如果您不这样做,那么 Firefox 会显示您发布的具有误导性的错误,但在其开发人员工具的深处,您会发现此错误:MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT。 This indicates that Firefox is not accepting the certificate at all because it is self-signed.这表明 Firefox 根本不接受该证书,因为它是自签名的。

AUG 2021: 2021 年 8 月:

const express = require('express');
const http = require('http');
const { Server } = require('socket.io');
const app = express();
const cors = require('cors');

app.use(
  cors({
    origin: ['https://americanairlines.com'],
    credentials: true,
    methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
    allowedHeaders: ['Origin', 'X-Requested-With', 'Content-Type', 'Accept'],
  })
);

const server = http.createServer(app);
const io = new Server(server, {
  cors: { origin: ['https://americanairlines.com'], credentials: true },
});

io.on('connection', async (socket) => {
  console.log('a user connected');
});

server.listen(5000);

Following code helped:以下代码有帮助:

const PORT = process.env.PORT || 4000;
const app = express();
const server = app.listen(PORT, () => {
    console.log(`Server running on port ${PORT}`);
});
const io = socket(server);

Acording with the doc (you can ignore the typescript stuff if you're using JS):根据文档(如果您使用的是 JS,则可以忽略打字稿的内容):

const io: Server = new Server(server, {
cors: {
    origin: "*",
    methods: ["GET", "POST"]
  },
});

这在 python-Flask-SocketIO 中对我有用

socketio =  SocketIO(app,cors_allowed_origins="*")

For me the symptom was CORS (No Access-Control-Allow-Origin header) and after spending hours trying everything here I realized that the remote webserver wasn't configured to handle https://serverurl/socket.io properly.对我来说,症状是 CORS(没有 Access-Control-Allow-Origin 标头),在花了数小时尝试这里的所有内容后,我意识到远程网络服务器未配置为正确处理 https://serverurl/socket.io。 After adding a nginx location handler for "/socket.io" the errors vanished.在为“/socket.io”添加 nginx 位置处理程序后,错误消失了。

安装 socket.io 版本 2 解决了我的问题

npm install socket.io@2

If you are using Express then define a middleware like this before your serve start code...如果您使用 Express,那么在您的服务启动代码之前定义一个这样的中间件......

app.use(function(request, response, next) {
  response.header("Access-Control-Allow-Origin", "*");
  response.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM