4
votes

Deploying my app on Heroku breaks websockets protocol.
It works on localhost, not on Heroku. In browser, I get :

WebSocket connection to 'wss://node-omi.herokuapp.com/socket.io/?EIO=2&transport=websocket&sid=*' failed: Error during WebSocket handshake: Unexpected response code: 503

On the server side, I get in logs:

2014-08-12T15:05:24.761611+00:00 heroku[router]: at=error code=H13 desc="Connection closed without response" method=GET path="/socket.io/?EIO=2&transport=websocket&sid=****" host=node-omi.herokuapp.com request_id=* fwd="*" dyno=web.1 connect=3ms service=3ms status=503 bytes=864

This is a part of my server script:

var express = require('express'),
    http = require('http'),
    socket_io = require('socket.io');
var app = express(),
    server = http.Server(app),
    io = new socket_io(server).of('/test');
io.on('connection', this.connection.bind(this));
app.get('/client.html', function(req, res, next) { ... });
app.use('/', express.static(__dirname + '/public', {'index': ['index.html']}));
server.listen(process.env.PORT || 5000);

What's wrong with my code ? Does anyone succeed in building a socket.io server with Express 4.8.3 and Socket.io 1.0.6 ? The socket works with polling, but I really need websockets to work. Thanks for replies.

1
I am having the same issue. The socket connects intermittently but usually has 503 or 400 errors. It means that I have 500+ timeout errors per day, even though the sockets appear to work.user2205763

1 Answers

3
votes

Websocket support on Heroku has since gone from beta to official support, so at the time of this post the fix might have been to simply labs:enable websockets But you should no longer need to do this, you get websockets out of the box.

Warning!

But as a warning to others reading this question, using socket.io on Heroku can be problematic because of a disagreement around sticky sessions

Heroku explicitly stands against them but (short of a rather crappy workaround described below) socket.io requires them:

https://github.com/Automattic/engine.io/issues/261

^The tl;dr if this very long thread is that before v1.0, socket.io worked with non-sticky services like Heroku, you just needed to use a redis adapter to manage shared state across your dynos. This was removed in 1.0 and the socket.io team is apprehensive to put it back due to the code maintenance cost. The github issue asking to have it back has been closed with the message that they'll be happy to look into it as soon as someone wants it badly enough to make a PR.

Workaround!

There is a workaround which is to restrict socket.io to using websocket transport only, which does not require sticky sessions. Eg:

Server:

io.set('transports', ['websocket']);

Client

var socket = io.connect(host, {
    transports: ['websocket']
});

However, this removes much of the benefit that socket.io 1.0 brings with its use of engine.io.

There are other websocket frameworks like Faye that work very nicely on Heroku.