Socket.io Chat on Dreamhost: Hiding the URL

My socket.io chat is accessible through the URL http://example.com:8080/. Dreamhost does not allow us to bind 80, so I am binding it on 8080.

I wanted to get rid of the port number in the URL. So, I used Dreamhost's Proxy Server feature (http://wiki.dreamhost.com/Proxy_Server), which is Apache's mod_proxy.

I proxied the port number 8080 to the URL http://example.com/socketchat. When I go to that URL, the chat does not work. I get this error:

"Proxy Error The proxy server received an invalid response from an upstream server. The proxy server could not handle the request GET /socket/. Reason: Error reading from remote server"

Is there a way to get rid of the port number in the URL that works with socket.io? If nothing works, would it be a security risk if I leave the port number in the URL when I launch my website to the public? Thanks.

My guess is that mod_proxy doesn't deal well with websockets, which is hardly surprising. That said, you really shouldn't put node.js behind Apache, as that defeats a lot of the purpose of node.js. Apache will quickly become your bottleneck.

Finally, no, there is no security risk with having socket.io on another port -- any security risk would be present regardless of which port you run it on. You might run into trouble with other firewalls, if they block connections to ports other than port 80 (which is not unheard of) -- but then again, such firewalls might present issues with websockets in any case.

Whether Apache quickly becomes a bottleneck or not depends on how you're using it exactly. It's a very mature web server and is hosting massive websites around the world just fine. Regardless, your socket.io application doesn't necessarily have to share the same port as your web application. You could have socket.io listen on port 8081, and have your normal http requests on port 8080. Then you would setup your proxy to point to 8080 as you have it now, and just have your socket.io connection go to 8081.

The port in this case shouldn't be a problem as it's not something a user would see in their URL, and the socket.io communication wouldn't have to go through the proxy. If you're serving enough requests for Apache to legitimately be a bottleneck, you should be able to spring for a better hosting environment anyway!

Example

Server

var app = require('http').createServer(handler)
  , io = require('socket.io').listen(8081)
  , fs = require('fs')

app.listen(8080);

function handler (req, res) {
  fs.readFile(__dirname + '/index.html',
  function (err, data) {
    if (err) {
      res.writeHead(500);
      return res.end('Error loading index.html');
    }

    res.writeHead(200);
    res.end(data);
  });
}

io.sockets.on('connection', function (socket) {
  socket.emit('news', { hello: 'world' });
  socket.on('my other event', function (data) {
    console.log(data);
  });
});

Notice that the webserver is listening on a separate port than the socket.io connection. This means you can safely proxy the normal http requests from 80 to 8080 using mod_proxy, and socket.io can communicate quite happily on port 8081 directly, bypassing the proxy. Your users will not have to type in a port in order to get to the site.

Client

<script src="http://domain.com:8081/socket.io/socket.io.js"></script>
<script>
  var socket = io.connect('http://domain.com:8081');
  socket.on('news', function (data) {
    console.log(data);
    socket.emit('my other event', { my: 'data' });
  });
</script>