Socket.io - Origin not allowed by Access-Control-Allow-Origin

I know there has been some discussion on this topic on SO, but I cant find the answer to my question. I have a web page running on the server with Aptana on localhost:8020. The javascript on the page is hitting a node server I have running on localhost:1337. Here is the node code:

var io = require('socket.io');
var http = require('http');
var sys = require('sys');
var json = [];
var server = http.createServer(function (req, res) {

  var headers = {};
  headers["Access-Control-Allow-Origin"] = "*";
  headers["Access-Control-Allow-Methods"] = "POST, GET, PUT, DELETE, OPTIONS";
  headers["Access-Control-Allow-Credentials"] = true;
  headers["Access-Control-Max-Age"] = '86400'; // 24 hours
  headers["Access-Control-Allow-Headers"] = "X-Requested-With, Access-Control-Allow-Origin, X-HTTP-Method-Override, Content-Type, Authorization, Accept";
  res.writeHead(200, headers);
  res.end();
});
server.listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
var socket = io.listen(server);
socket.on('connection', function(){
  console.log("Connected");
});

I am handling the cors request by changing the headers, which I do all the time. My client side code is typically socket.io beginner stuff. Here is the tag from my code:

<script src="http://cdn.socket.io/stable/socket.io.js"></script>
    <script>

        // Create SocketIO instance
        var socket = new io.Socket('localhost',{
            port: 1337
        });
        socket.connect();

        // Add a connect listener
        socket.on('connect',function() {
            log('<span style="color:green;">Client has connected to the server!</span>');
        });
        // Add a connect listener
        socket.on('message',function(data) {
            log('Received a message from the server:  ' + data);
        });
        // Add a disconnect listener
        socket.on('disconnect',function() {
            log('<span style="color:red;">The client has disconnected!</span>');
        });

        // Sends a message to the server via sockets
        function sendMessageToServer(message) {
            socket.send(message);
            log('<span style="color:#888">Sending "' + message + '" to the server!</span>');
        }

        // Outputs to console and list
        function log(message) {
            var li = document.createElement('li');
            li.innerHTML = message;
            document.getElementById('message-list').appendChild(li);
        }

When I run the code I keep getting 'XMLHTTPRequest...Origin is not allowed by Access-Control-Allow-Origin' errors. My browser is chrome. 1. Why is my browser using XMLHTTPRequest and not a Websocket? 2. Why am I getting a Access control error when I am changing the headers? Thanks for all the help in advance.

Your custom headers actually never get written for socket.io related requests.

Socket.IO overrides some methods of the http server. One of them is the triggering of the 'request' handlers. Socket.IO only allows itself to be the primary handler of all requests. Then it tests if the request is actually a socket.io request (based on the prefix of the path requested). If it determines that it shouldn't handle a given request, it triggers other 'request' handlers.

You can see that by just putting a console.log statement before your writeHead call and you'll see that nothing appears in stdout.

Reading the source code, it seems that socket.io automatically sets a Access-Control-Allow-Origin header with the value of the origin header of the request. I would assume there is a way to set such a header on the client as well.

So, to clear things up:

1 Your browser falsl back to xhr-polling because it doesn't support websockets or websocket transport fails silently

2 The headers you set yourself in the httpServer request event never get sent, so they have no action on the origin Policy.

solution: find a way to set the origin header on the request. After crawling throught the client code, I have found no evidence that this can be done easily.

According to socket.io documentation, you should be able to set both priority of the transports (and maybe skipping one if it creates problems) and configure socket.io origins directly.

    io.set('transports', ['websocket', 'xhr-polling', 'jsonp-polling', 'htmlfile', 'flashsocket']);
    io.set('origins', '*:*');

One thing to note is that the '*' value cannot be used in the Access-Control-Allow-Origin header when Access-Control-Allow-Credentials is true. Either remove the Access-Control-Allow-Credentials header, or set Access-Control-Allow-Origin to the value of the request Origin header.