Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Cannot GET" on reverse proxy from Nginx to socket.io on express.js

I've followed this tutorial to get Node.js working through Nginx on a two Ubuntu 14.04 servers via private networking (Node.js is on myappserver - accessible via private IP myprivatewebserver and publicly via mypublicappserver - and Nginx on mywebserver). Everything works fine til this point - I can access a node.js application on myprivateappserver:3000 proxied via Nginx by going to http://mywebserver/node.

However, when I try and run up the chat application in socket.io on express.js, it works when I access it directly (http://mypublicappserver:3000) but, when I try and access it via my Nginx proxy (http://mywebserver/node), I get "Cannot GET /node" in the browser and in the firebug console " "NetworkError: 404 Not Found - http://mywebserver/node".

If I curl http://myprivateappserver:3000 from mywebserver, I get index.html from my socket.io application fine.

My /etc/nginx/sites-available/default contains:

location /node{
proxy_pass http://myprivateappserver:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}

My index.js is:

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

app.get('/', function(req, res){
  res.sendFile(__dirname + '/index.html');
});

io.on('connection', function(socket){
  console.log('a user connected');
  socket.on('disconnect', function(){
    console.log('user disconnected');
  });
  socket.on('chat message', function(msg){
    io.emit('chat message', msg);
  });
});

http.listen(3000, function(){
  console.log('listening on *:3000');
});

and my index.html is:

<!doctype html>
<html>
  <head>
    <title>Socket.IO chat</title>
    <style>
      * { margin: 0; padding: 0; box-sizing: border-box; }
      body { font: 13px Helvetica, Arial; }
      form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }
      form input { border: 0; padding: 10px; width: 90%; margin-right: .5%; }
      form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }
      #messages { list-style-type: none; margin: 0; padding: 0; }
      #messages li { padding: 5px 10px; }
      #messages li:nth-child(odd) { background: #eee; }
    </style>
  </head>
  <body>
    <ul id="messages"></ul>
    <form action="">
      <input id="m" autocomplete="off" /><button>Send</button>
    </form>
    <script src="/socket.io/socket.io.js"></script>
    <script src="http://code.jquery.com/jquery-1.11.1.js"></script>
    <script>
      var socket = io();
      $('form').submit(function(){
        socket.emit('chat message', $('#m').val());
        $('#m').val('');
        return false;
      });
      socket.on('chat message', function(msg){
        $('#messages').append($('<li>').text(msg));
      });
    </script>
  </body>
</html>

This is my first foray into nginx/node/express/socket (I'm normally an Apache/CakePHP person) so I may well be missing something very simple but would also be very grateful for any pointers on how to debug what's going wrong

like image 999
theotherdy Avatar asked Jul 16 '15 14:07

theotherdy


1 Answers

This is because SocketIO uses /socket.io path by default, so you need to configure Nginx so that it will proxy not only /node request, but /socket.io too:

location ~ ^/(node|socket\.io) {
    #your proxy directives
}

(By the way, it looks like you have typos: you wrote proxypass, but the correct form is proxy_pass. The same goes to other proxy directives)

You also need to perform one more edit in your NodeJS server file. Replace:

app.get('/', function(req, res){

with:

app.get('/node', function(req, res){

Now it should work.

This is not the only solution. You could also change SocketIO path with some changes in Nginx config, but the solution described above seems the simlest to me. Good luck!

like image 184
Oleg Avatar answered Nov 15 '22 06:11

Oleg