25

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.

Akhilesh Kumar
  • 9,085
  • 13
  • 57
  • 95

12 Answers12

62

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.

Peter Weyand
  • 2,159
  • 9
  • 40
  • 72
Akhilesh Kumar
  • 9,085
  • 13
  • 57
  • 95
45

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"],
}
Shree Charan
  • 573
  • 5
  • 8
  • 1
    This works in 2020! (unlike everything else I found) – user8555937 Nov 10 '20 at 19:57
  • 1
    This works like a charm should be the the accepted answer. – Selam Getachew Nov 15 '20 at 11:31
  • 6
    Nope. I'm also in 2020, and this is not working. It's also not what the docs for 3.x say, but what it says to do for 3.x does not work either. Socket.io sucks. – Spencer Williams Dec 12 '20 at 04:06
  • @SpencerWilliams check out this https://stackoverflow.com/questions/55292478/socket-io-cors-blocked/65069469#65069469 maybe this work for you. its tricky by the way. – Shamshirsaz.Navid Dec 12 '20 at 06:59
  • 1
    The origins parameter isn't doing anything here. If you set cors to true, you're allowing all requests. You need to set cors to an object with 'origin' in it as a string or an array of accepted origins: cors: { origin: ['http://127.0.0.1:800'] } Documentation: https://github.com/expressjs/cors#configuration-options – CptBB Dec 12 '20 at 19:43
  • 1
    @Shamshirsaz.Navid Thank you for the link. I did get this to work. The error was misleading. The issue was due to me not specifying the right port for the client socket.io to connect to because of port mappings into a container. It is now respecting the socket.io cors setting when I am simply using the `http` module. – Spencer Williams Dec 14 '20 at 01:52
  • @SpencerWilliams You are welcome :) also; yesterday, I found-out my answer is deprecated and I changed it. – Shamshirsaz.Navid Dec 14 '20 at 07:37
  • Thank you! This is the only thing that helped. Cheers from 2021. – Vincurekf Jul 09 '21 at 22:30
4

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

Pascal
  • 353
  • 2
  • 11
2

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"]
  },
});
2

AUG 2021:

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

Meir
  • 516
  • 4
  • 19
1

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.

Flyn Sequeira
  • 718
  • 2
  • 9
  • 25
1

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.

tsaixingwei
  • 636
  • 9
  • 13
0

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);
user3338348
  • 11
  • 1
  • 4
0

This worked for me in python- Flask-SocketIO

socketio =  SocketIO(app,cors_allowed_origins="*")
SARIM
  • 992
  • 3
  • 14
  • 22
0

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. After adding a nginx location handler for "/socket.io" the errors vanished.

phkla1
  • 1
  • 1
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Feb 10 '22 at 15:22
-2

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

Installing socket.io version 2 solved my problem

npm install socket.io@2
ASANIAN
  • 372
  • 2
  • 8