Socket.io + Node.js Cross-Origin Request Blocked

I'm using node and socket.io to write a chat application. It works fine on Chrome but mozilla gives an error to enable the Cross-Origin Requests.

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://waleedahmad.kd.io:3000/socket.io/?EIO=2&transport=polling&t=1401964309289-2&sid=1OyDavRDf4WErI-VAAAI. This can be fixed by moving the resource to the same domain or enabling CORS.

Here's my code to start node server.

var express = require('express'),
    app = express(), 
    server = require('http').createServer(app),
    io = require('socket.io').listen(server),
    path = require('path');
server.listen(3000);

app.get('/', function(req, res) {
    res.sendfile(__dirname + '/public/index.html');
});

On the client side.

var socket = io.connect('//waleedahmad.kd.io:3000/');

Script tag on HTML page.

<script type="text/javascript" src="//waleedahmad.kd.io:3000/socket.io/socket.io.js"></script>

I'm also using .htaccess file in the app root directory. (waleedahmad.kd.io/node).

Header add Access-Control-Allow-Origin "*"
Header add Access-Control-Allow-Headers "origin, x-requested-with, content-type"
Header add Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS"

Simple Server-Side Fix

❗ DO NOT USE "socketio" package... use "socket.io" instead. "socketio" is out of date. Some users seem to be using the wrong package.

❗ I do not condone setting origin to * as this opens up the ability for phishing sites to imitate the look and feel of your site and then have it work just the same. If you set the origin, you can avoid this.

socket.io v3

docs: https://socket.io/docs/v3/handling-cors/

cors options: https://www.npmjs.com/package/cors

const io = require('socket.io')(server, {
  cors: {
    origin: '*',
  }
});

socket.io < v3

const io = require('socket.io')(server, { origins: '*:*'});

or

io.set('origins', '*:*');

or

io.origins('*:*') // for latest version

* alone doesn't work which took me down rabbit holes.


I am using v2.1.0 and none of the above answers worked for me. This did though:

import express from "express";
import http from "http";

const app = express();
const server = http.createServer(app);

const sio = require("socket.io")(server, {
    handlePreflightRequest: (req, res) => {
        const headers = {
            "Access-Control-Allow-Headers": "Content-Type, Authorization",
            "Access-Control-Allow-Origin": req.headers.origin, //or the specific origin you want to give access to,
            "Access-Control-Allow-Credentials": true
        };
        res.writeHead(200, headers);
        res.end();
    }
});

sio.on("connection", () => {
    console.log("Connected!");
});

server.listen(3000);

You can try to set origins option on the server side to allow cross-origin requests:

io.set('origins', 'http://yourdomain.com:80');

Here http://yourdomain.com:80 is the origin you want to allow requests from.

You can read more about origins format here


For anyone looking here for new Socket.io (3.x) the migration documents are fairly helpful.

In particular this snippet:

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

I tried above and nothing worked for me. Following code is from socket.io documentation and it worked.

io.origins((origin, callback) => {
  if (origin !== 'https://foo.example.com') {
      return callback('origin not allowed', false);
  }
  callback(null, true);
});