darylhedley
darylhedley

Reputation: 258

How do I setup NGINX with a reverse proxy to port 80 for two apps that both need socket.io?

I've been going around this for a couple few days now. I get so close and then a connection seems to die or socket.io cannot be found. But then maybe I'm doing it wrong?

My NGINX files looks something like this:

upstream appOne {
    server demo.someserver.com:1111;
}

upstream appTwo {
    server demo.someserver.com:2222;
}

location /appOne/ {
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    proxy_pass http://appOne/;
}
location /appTwo/ {
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    proxy_pass http://appTwo/;
}

location /socket.io/ {
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    proxy_pass http://appOne/socket.io/;
}

So what I'm trying to do here is have appOne running in a subfolder at demo.someserver.com/appOne and have appTwo running in a subfolder at demo.someserver.com/appTwo but both have a reverse proxy.

All connects great except both apps need socket.io to run and shouldn't really need to connect to each other (Although I'm starting to think this wouldn't be a bad idea). But at the moment they both connection to appOne/socket.io/socket.io.js because of the last NGINX location. This causes all sorts of problems when connecting like the socket connection not being on the same port etc.

What I'm trying to avoid is naming the ports and the app name inside any frontend JS files as appOne and appTwo in this context could be clientOne and clientTwo.

I did think of something like this:

if ($request_uri == 'appOne') {
    proxy_pass http://appOne/socket.io/;
}
if ($request_uri == 'appTwo') {
    proxy_pass http://appTwo/socket.io/;
}

But I have no idea how that actually works. Any pointers or has anyone tried to do something the same?

So my question is - how can I have separate connections to socket.io through the reverse proxy. Or should I have one socket.io connection and both attach to that? (but I could have multiple clients on one server)

Upvotes: 1

Views: 682

Answers (2)

Oleg
Oleg

Reputation: 23277

If you need two separate socket.io apps, you can perform this by setting (undocumented) path option when initializing socket.io on the client.

To be consistent, I will provide you full working example of Nginx config and Node files:

nginx config:

upstream appOne {
    server demo.someserver.com:1111;
}

upstream appTwo {
    server demo.someserver.com:2222;
}

server {
    listen          80;
    server_name     demo.someserver.com;
    root            /path/to/working/dir; #probably not necessary

    location /appOne/ {
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_pass http://appOne/;
    }
    location /appTwo/ {
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_pass http://appTwo/;
    }
    # no need for /socket.io location
    # each app will connect socket.io via /appOne/socket.io or /appTwo/socket.io
}

app1.js and app2.js (Express + Socket.io example):

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

var port = 1111; //or 2222 for app2.js

app.get('*', function(req, res) {
    res.sendFile(__dirname + '/index1.html');  //or index2.html for app2.js
});

io.on('connection', function(socket) {
    socket.emit('hello', {port: port});
});

server.listen(port);

index1.html and index2.html:

<!DOCTYPE html>
<html>
<head>
<script src="/appOne/socket.io/socket.io.js"></script>
<!--<script src="/appTwo/socket.io/socket.io.js"></script>-->
<script>
var socket = io('/', {path: '/appOne/socket.io'});
//var socket = io('/', {path: '/appTwo/socket.io'});
socket.on('hello', function(data) {
    console.log(data.port);
});
</script>
</head>
<body>

<h1>app</h1>

</body>
</html>

So if you launch both app1.js and app2.js and navigate to

http://demo.someserver.com/appOne

and then

http://demo.someserver.com/appTwo

you will see in your console 1111 and 2222 respectively, which means that you have two independent socket.io apps.

Upvotes: 5

Tan Hong Tat
Tan Hong Tat

Reputation: 6864

You can set a custom path to socket.io in your script.

Sets the path v under which engine.io and the static files will be served. Defaults to /socket.io.

If no arguments are supplied this method returns the current value.

Source: http://socket.io/docs/server-api/#server#path%28v:string%29:server

Upvotes: 0

Related Questions