Search code examples
node.jssocket.iodreamhost

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.


Solution

  • 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>