20
votes

My node server and client are running on different ports(3001,5347 respectively). 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. A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true. Origin 'null' is therefore not allowed access.

Note: I'm using express on server and I'm already using cors middleware in following way:

app.use(cors());

Where app and cors are instances of express and cors respectively.

10
how did you fix this? - Pragati Dugar

10 Answers

58
votes

If running Express as follows:

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

So to start socket.io, we can do the following:

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.

36
votes

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

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

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

Back in 2014 they added support for method as part of the origin parameter:

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:

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

While migrating to socket.io v3.0+, there is a migration change on how to setup CORS. https://socket.io/docs/v3/migrating-from-2-x-to-3-0/index.html#Configuration

Before 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:

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

1
votes

Note that you can use cors() with app before you pass app into require('http'), which is then passed into 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.

1
votes

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.

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. This indicates that Firefox is not accepting the certificate at all because it is self-signed.

0
votes

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);
0
votes

Acording with the doc (you can ignore the typescript stuff if you're using JS):

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

This worked for me in python- Flask-SocketIO

socketio =  SocketIO(app,cors_allowed_origins="*")
-1
votes

Installing socket.io version 2 solved my problem

npm install socket.io@2
-3
votes

If you are using Express then define a middleware like this before your serve start code...

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();
});