Socket.io events not received (nginx reverse proxy, server to client) - node.js

I have a nodejs socket.io app running under nginx reverse proxy.
My nginx configuration is as follows:
location ~ ^/(online|socket\.io) {
proxy_pass http://localhost:8888;
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;
}
This seems to work, and my nodejs app picks up the connection fine. On the server side socket.io I have the following:
io.of('/online').on('connection', function(socket){
This seems to work fine, and the 'connection' event is firing
The problem arises when I try to emit an event from the server to the client:
socket.join("users");
io.sockets.in("users").emit("got_users",users);
The 'got_users' event is not being picked up by the client. On the client side I have the following:
a4e.socket=io.connect('http://www.example.com/online');
This seems to work fine, but then:
a4e.socket.on("got_users",function(online_users){
This doesn't pick up the "got_users" event, no matter what I try.
Any help greatly appreciated.

I finally figured this out, the following line:
io.sockets.in("users").emit("got_users",users);
Should be replaced with:
io.of("/online").in("users").emit("got_users",users);
Then it works.

Related

Cannot GET etc with Nginx Reverse Proxy React + Node + PM2

In setting up an Nginx reverse proxy for both a React app and a Node web server, it seems to have broken Express on the backend, although I can tell I'm accessing it in the browser by receiving "Cannot GET XX" messages after adding the second location block soon to follow below (previously the browser was just white when visiting the API endpoints because React Router was trying to grab them).
Here's what the config looks like, where port 3000 is my React app and 4000 is my Express server, both being managed by pm2:
server {
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name www.mywebsite.com; # managed by Certbot
location / {
proxy_pass http://127.0.0.1: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;
}
location /api/ {
proxy_pass http://127.0.0.1:4000/;
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;
}
}
Simple Express route that won't work ("Cannot GET /"):
app.get('/', (req, res) => {
res.send('Hello, world!');
});
There is some additional certbot stuff that was generated for SSL, but I'm not sure it's relevant. The React app works perfectly, but whether it's "location /api/" vs "location /api" and no matter how I name my routes in Express, they all can't resolve despite having worked perfectly before. Thanks in advance for any guidance!
EDIT: I changed the server conf to at least map /api/ to my server's root with a trailing backslash so I don't have to prepend /api to every route handler, but the issue still remains ("Cannot GET /").
Why do you use the following headers?
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
Probably not needed if you are using TLS/https and it may be causing issues with express if the upgrade header exists. Try removing that.
These headers are generally used for WebSockets. See the nginx docs for more details.

Socket.io not working with nginx and https

I have a React app communicating with a very simple node backend, it works perfectly fine in local and was working perfectly fine over http. For obvious reason, the app is now running in https but the socket is not connecting anymore. I have been looking to so many threads but couldn't find a way to fix it. Here are the socket parts of my code and nginx conf.
Client side:
const socket = io('wss://sub.domain.io', { path: '/my-path',});
Server side:
const server = require('http').createServer();
const io = require('socket.io')(server, {
path: '/my-path',
serveClient: false
});
server.listen(8080);
nginx proxy
server {
....website serving part...
location /my-path/ {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
Error is: GET https://sub.domain.io/my-path/?EIO=3&transport=polling&t=MsCot3e net::ERR_CONNECTION_TIMED_OUT VM17:1 which looks like a timeout because it fails to connect.
So I found an answer after so many hours and it is pretty dumb and simple. My Nginx only handle the www website (DNS redirection is enough for the website), hence I needed www.sub.domain.io here:
const socket = io('wss://www.sub.domain.io', { path: '/my-path',});

Laravel Socket.io Cross-Origin denied

I'm trying to deploy my laravel app with socket.io and I have everything up and running. Node, redis, etc. but when socket event is fired I get this exact error message.
XMLHttpRequest cannot load http://localhost/socket.io/?EIO=3&transport=polling&t=Lbe2fnV. Cross-origin redirection denied by Cross-Origin Resource Sharing policy.
I have gone into my nginx config file and added the following:
upstream app_yourdomain {
server 127.0.0.1:3000;
keepalive 8;
}
location ~* \.io {
proxy_pass http://localhost: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;
}
but it doesn't do anything.
How can I get rid of the cross-orgin error?
My biggest success came from this post
NodeJS server on DigitalOcean using socket.io returns connection refused
Try to set the origins property like so.
io.set('origins', 'http://localhost:3000');
You can put in every url you allow to get the request from for example
io.set('origins', 'http://google.com:80');
or allow all
io.set('origins', '*:*');
More about the origin property can be found here

Client can not interact together when using nginx with socket.io

I have a chat application using socket.io. I put code on 2 server (ip1, ip2) and using nginx to make load balancing.
this is nginx config
upstream socket_nodes {
ip_hash;
server ip1:1654;
server ip2:1653;
}
server {
listen 1653;
server_name livechatsoftware.com.vn;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-NginX-Proxy true;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://socket_nodes;
proxy_redirect off;
}
}
Everything is working well if clients connect to same server. but if client 1 connect to server ip1, client 2 connect to server ip2. client 1 and client 2 can not interact (eg cannot emit, send message,....)
Thanks for advance
I am using nginx to load balance my node processes (express.js + mongodb + socket.io + passport.js) . Although they are all in the same server, still socket.io events don't get shared between them. That means I've also faced the exact same issue. So I've used mong.socket.io (https://github.com/tmfkmoney/mong.socket.io) to store socket.io events in the mongo store. In that way each socket.io process reads the events from a centralized store.
You also need a central store which socket.io events can be accessed from any of the servers. I've never used that kind of setup but check out the below package;
https://www.npmjs.com/package/socket.io-redis
I'd install redis to one of my servers and point my socket.io processes to that server like below;
io.adapter(redis({ host: 'localhost', port: 6379 })); // you should use ip address and the port for the remote server
You can also use other adapter options as mentioned in the past link I've shared.

Nodejs (sailsjs), NGINX and sails.io (socket.io)

I'm using NGINX to handle my Nodejs servers and now I want to start using socket.io on them, doing research before starting to play with socket.io i found Sailsjs which I grew rather found of and now currently using.
The problem I meet though, is that the client can't connect through NGINX on socket.io, or sails.io.
This is the URL path for my current APP:
https://localhost/economy
And the url for sails.io is, as standard:
https://localhost/economy/assets/js/dependencies/sails.io.js
Now!
Using FileSeek I found out where sails.js use "require("socket.io")", which is in the "loadSocketIO.js" (node_modules\sails\lib\hooks\sockets\lib). I edited the file to say:
var io = sails.io = sails.ws =
SocketServer.listen(sails.hooks.http.server, {
resource: 'economy',
logger: {
info: function (){}
}
});
adding the resource: 'economy', line.
Then on the client side I did the same:
var socket = io.connect('https://localhost/economy/socket.io', { resource: 'economy' });
I've been playing with this and tried different ways, like "economy/socket.io", the full socket.io path etc.
Any help, is a lot of help!
I've been struggling for a day now so I figured i'd ask for some help :)
You shouldn't need to change anything on the Sails side. Try reading up on proxy_pass for your location directive in Nginx.
http://nginx.org/en/docs/http/websocket.html
This is an excerpt from the above link:
location /chat/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://localhost:1337;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
SOLUTION!
Run everything as it is, the only part you have to edit is in NGINX.
set a server block with the servername as economy.localhost/, and you're done :)
Remember to link economy.localhost to 127.0.0.1 or set a cname if this is a production server :)
The example showed here worked for me.
Basically for nginx WebSocket support you need to include the following config.
server {
server_name app.domain.com;
location / {
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://localhost:8080;
}
}

Resources