Unexpected response code: 502 error when using socket.io with AppFog

Andrew Liu picture Andrew Liu · Sep 24, 2012 · Viewed 23.9k times · Source

The error

When the user opens http://sync.aws.af.cm/, the Google Chrome JavaScript Console shows (within a few seconds):

Unexpected response code: 502 error

The app should remember the contents of the text area even after the user refreshes the page. The app works locally, but not when I upload it to AppFog, and I suspect the problem is the 502 error.

Do you know what might cause this error in this case?

What I've tried

I tried changing the script src=<path_to_socket_io> path in my client from /socket.io/socket.io.js to node_modules/socket.io/node_modules/socket.io-client/dist/socket.io.js as described here, but it did not help.

I also tried serving the app at Heroku instead of AppFog, but in that case I kept running into the issue described here even though I specified socket.io version 0.9.6.

I've also looked at the following questions, but the comments so far don't seem to help me.

socket.io creating 502 Bad Gateway on connect / websocket invalid

Socket.IO node.js websocket connection invalid port 8081

socket.io with node.js not working as expected

Relevant server code

Here is the relevant server code:

var server = http.createServer(function (req, res) {
  ...
});

var io = require('socket.io').listen(server);

// Define events that can be triggered by the client
io.sockets.on('connection', function (socket) {
  socket.on('setServerVariable', function (value) {
    ...
  });
  ...
});

server.listen(process.env.VCAPP_APP_PORT || 3000);

Relevant client code

<script src="/socket.io/socket.io.js"></script>

<script>
  window.onload = function () {
    ...
    var socket = io.connect(window.location.hostname);
    socket.emit('getServerVariable');
    ...
  };
...

Server log

$ af logs sync

====> /logs/stdout.log <====

info: socket.io started
debug: served static content /socket.io.js
debug: client authorized
info: handshake authorized veNnUVtoDTIz-oudG7Pa
debug: setting request GET /socket.io/1/websocket/veNnUVtoDTIz-oudG7Pa
debug: set heartbeat interval for client veNnUVtoDTIz-oudG7Pa
warn: websocket connection invalid
info: transport end (undefined)
debug: set close timeout for client veNnUVtoDTIz-oudG7Pa
debug: cleared close timeout for client veNnUVtoDTIz-oudG7Pa
debug: cleared heartbeat interval for client veNnUVtoDTIz-oudG7Pa
debug: served static content /socket.io.js
debug: client authorized
info: handshake authorized 6AKyhROUNjqujk_uG7Pb
debug: setting request GET /socket.io/1/websocket/6AKyhROUNjqujk_uG7Pb
debug: set heartbeat interval for client 6AKyhROUNjqujk_uG7Pb
warn: websocket connection invalid
info: transport end (undefined)
debug: set close timeout for client 6AKyhROUNjqujk_uG7Pb
debug: cleared close timeout for client 6AKyhROUNjqujk_uG7Pb
debug: cleared heartbeat interval for client 6AKyhROUNjqujk_uG7Pb
debug: setting request GET /socket.io/1/xhr-polling/6AKyhROUNjqujk_uG7Pb?t=1348504130465
debug: setting poll timeout
debug: client authorized for 
debug: clearing poll timeout
debug: xhr-polling writing 1::
debug: set close timeout for client 6AKyhROUNjqujk_uG7Pb
debug: setting request GET /socket.io/1/xhr-polling/6AKyhROUNjqujk_uG7Pb?t=1348504130724
debug: setting poll timeout
debug: discarding transport
debug: cleared close timeout for client 6AKyhROUNjqujk_uG7Pb
debug: xhr-polling received data packet 5:::{"name":"getServerVariable"}
debug: clearing poll timeout
debug: xhr-polling writing 5:::{"name":"printLog"}
debug: set close timeout for client 6AKyhROUNjqujk_uG7Pb
server.js: getServerVariable: 
debug: setting request GET /socket.io/1/xhr-polling/6AKyhROUNjqujk_uG7Pb?t=1348504130980
debug: setting poll timeout
debug: clearing poll timeout
debug: xhr-polling writing ���23���5:::{"name":"printLog"}���39���5:::{"name":"setItemValue","args":[""]}���23���5:::{"name":"printLog"}
debug: set close timeout for client 6AKyhROUNjqujk_uG7Pb
debug: discarding transport
debug: cleared close timeout for client 6AKyhROUNjqujk_uG7Pb
debug: setting request GET /socket.io/1/xhr-polling/6AKyhROUNjqujk_uG7Pb?t=1348504131261
debug: setting poll timeout
debug: discarding transport
debug: cleared close timeout for client 6AKyhROUNjqujk_uG7Pb
debug: clearing poll timeout
debug: xhr-polling writing 8::
debug: set close timeout for client 6AKyhROUNjqujk_uG7Pb
debug: xhr-polling closed due to exceeded duration
debug: setting request GET /socket.io/1/xhr-polling/6AKyhROUNjqujk_uG7Pb?t=1348504151659
debug: setting poll timeout
debug: discarding transport
debug: cleared close timeout for client 6AKyhROUNjqujk_uG7Pb

Answer

Wes Johnson picture Wes Johnson · Sep 25, 2012

AppFog doesn't support websockets yet. Following their recent acquisition of Nodester, they announced it would be coming in a few months.

By adding io.set('transports', ['xhr-polling']); you're just setting the transport to ajax long polling. By default, Socket.io determines the best transport based on browser capabilities and the current connection. Websockets is ideal, when it's available, but if it's not Socket.io will fall back to xhr-polling among other transports.

I received the same 502 unexpected response / bad gateway error myself when using CloudFlare which is also unable to proxy websocket connections via its nginx-based infrastructure (note that as of 2014, Cloudflare can proxy websockets if you're on a premium plan).