4

In my web application I use Node.js and Socket.io.

As I testet the application local or in my wifi network everything was fine but since I switched to mobile data I get the connection error:

WebSocket connection to 'ws://url/socket.io/1/websocket/' failed: Error during WebSocket handshake: Unexpected response code: 502

It seems that my mobile provider is blocking the ports 8080 and 80 but switching to another port seems not possible with nodejitsu.

Has someone some experience how to handle mobile network, node.js and socket.io?

EDIT:
As host I tried a free subscription of Heroku and a free subscription of Nodejitsu.

On mobile I checked the ports on http://websocketstest.com/ with mobile and wifi. On mobile the test failed with the ports 80 and 8080.
I thought maybe I could change the port to 443 but nodejitsu seems to listen to port 80 even if I set server.listen() to port 443.

I think WebSockets could be possible maybe via another port but I don't know how to change the port or why nodejitsu for example is just listening to port 80.

Yves
  • 1,144
  • 1
  • 24
  • 30

3 Answers3

3

HTTP 502 means "Bad Gateway" and usually the sign of a reverse proxy somewhere along the path between client and server.

If you're sure it's not because of your own setup, you should try to disable the websocket (and flashsocket) transports for socket.io:

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

io.set('transports', [ 'xhr-polling', 'jsonp-polling', 'htmlfile' ]);
robertklep
  • 174,329
  • 29
  • 336
  • 330
  • I tried it but it seems via polling I get a massive latency. Could you please explain in more detail what do you mean by "A 'Bad Gateway' is usually the sign of a reverse proxy". – Yves Nov 26 '13 at 20:16
  • @yves can you explain (by editing your question) what your exact server setup is? Is your Node app directly exposed to the outside world, or are you using something like nginx too? On what port(s) is your server listening? I agree that using a polling transport is really bad for latency, but if the problem is with your mobile provider not being able to handle WebSocket connections properly, you can't really do anything. – robertklep Nov 26 '13 at 20:19
  • @yves I think it's either your mobile provider's fault, *or* you're using some form of mobile data compression service (like Opera Turbo). – robertklep Nov 26 '13 at 21:41
  • It seems to work if I call the page via `https` because then it's using the port 443. – Yves Dec 01 '13 at 22:27
  • @yves yes, very much sounds like your mobile provider is proxying plain HTTP traffic, which is causing problems with WebSockets – robertklep Dec 02 '13 at 07:37
1

You must set data transport configuration:

var io= require('socket.io');
io.set("transports", ["xhr-polling"]);
Reza Ebrahimi
  • 3,278
  • 1
  • 24
  • 37
  • Thanks, I resolved this [deployd](https://github.com/deployd/deployd/issues/429) error thanks to your post !! – hugsbrugs Nov 27 '14 at 15:39
1

Your node.js app uses websockets and works locally and over a wifi network. When using mobile data network it fails with a 502. This is the question I'm answering not the heroku/nodejitsu edit.

The most probable reason for this is a bad hop in the network e.g. a reverse proxy. To use Websockets through a reverse proxy you must use http1.1 and upgrade on connect to go from http to ws protocols. Some proxies do not (yet) support http upgrade, some other things (e.g. @roberklep Opera Turbo) mangle that so websockets don't work.

Moving from http on port 80 to https on port 443 (using SSL which is now known as TLS) encrypts the data at the transport layer. Most of those bad hops are set up to send that data straight through which clears up your problem.

I found another StackOverflow Q&A showing some code setting up https in node.js The key bits of that post being:

var sslOptions = {
  key: fs.readFileSync(__dirname + '/../ssl/server.key,
  cert: fs.readFileSync(__dirname + '/../ssl/server.pem,
  ciphers: 'ECDHE-RSA-AES256-SHA:AES256-SHA:RC4-SHA:RC4:HIGH:!MD5:!aNULL:!EDH:!AESGCM',
  honorCipherOrder: true };

and

var server = https.createServer(sslOptions, app); server.listen(443);

I also found a useful introduction to SSL/TLS that includes instructions on how to get a free certificate.

Community
  • 1
  • 1
WorkingMatt
  • 585
  • 7
  • 21