Getting CORS error while using socket.io / nginx / node - node.js

I'm getting this error log from chrome's console
XMLHttpRequest cannot load https://subgroup.domain.com/socket.io/?EIO=3&transport=polling&t=Lpgp_mu. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 500.
I am using Node.js, socket.io to talk between my node and react.js, with a digitalocean's droplet using nginx to host them.
I've been reading a lot about CORS errors and I am unsure where to fix the error. I've been trying to allow them in my NGINX
location /server {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Access-Control-Allow-Origin *;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
And from my node.js, server side:
var express = require("express");
var app = express();
var http = require("http");
var port = 8080;
var io = require("socket.io").listen(app.listen(port));
app.use("/", function (req, res, next) {
res.status(200).send("Online |" + " Version : [" + AppVersion + "]");
res.setHeader("Access-Control-Allow-Origin","*");
res.setHeader("Access-Control-Allow-Headers","X-Requested-With,content-type");
res.setHeader("Access-Control-Allow-Methods","GET,POST, OPTIONS, PUT, PATCH, DELETE");
next();});
And I connect on the client side using:
const socket = io.connect("https://subgroup.domain.com/server")
I am not really sure where and what I should look for. Any kind of help would help. Thanks!

After a long research and executing multiple tests I got this working. Here is what I did,
NodeJS
const server = require('http').createServer();
const io = require('socket.io')(server);
io.on('connection', (socket) => {
console.log('A user connected!');
io.emit('welcome', 'Hello there!');
});
server.listen(3001);
console.log('Socket server started on port 3001');
Nginx
upstream websocket1 {
server 127.0.0.1:3001;
}
server {
listen 80;
listen [::]:80;
root /var/www/html;
server_name mydomain.com
location /ws/ {
proxy_pass http://websocket1/socket.io/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Finally on the client side
const socket = io.connect('http://yourdomain.com/', {path: '/ws/'})
Here is a screenshot from Chrome console.
Please do not ignore the / after specifying the location in Nginx, it must be /ws/ it is not working otherwise. Currently I have a node balancer added to this socket service with Nginx.
Cheers!

Related

Using Nginx as proxy for Node.js' Express and Socket.io

I want to run an express server and a socket.io server on an node.js instance which are reachable through nginx. If possible, I would favor to run them both on the same port, but I did not reach that goal either.
I can reach the webserver locally and from extern.
I can only reach the socket server locally.
When I call the page, my browsers log shows the following error:
GET https://example.com/socket.io/?EIO=3&transport=polling&t=O6qCW5Y
400 Bad Request
So I think the problem lies somewhere in the nginx config.
My app.js code for the socket.io server:
const http = require('http').createServer();
const io = require('socket.io')(http);
http.listen(3001, () => {
console.log('Socket-Server listening on port: 3001');
});
io.on('connection', (socket) => {
...
});
My code for the client:
window.onload = function() {
const socket = io.connect('https://box-api.com/');
socket.on('connect', () => {
...
}
}
My nginx config:
server {
server_name example.com;
root /nodejs/example.com;
include static_files.conf;
index app.js;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
}
location /socket.io {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# Certbot stuff
...
}

Socket.io Socket.onPacket Error with reverse proxy Nginx

I have a small angular app who comunicate with a node.js server. Both are deployed on aws and I use Nginx reverse proxy to acess the node.js server at the port 4000.
All end-points of the nodejs.server works fine, except the socket.io connection.
When I run both apps (front end app and the node.js server) in my machinine the socket.io connection works fine, but when I try to deploy it on aws I get this error in the front-end app:
Error: server error
at Socket.onPacket (socket.js:401)
at XHR.<anonymous> (socket.js:216)
at XHR.push.dMso.Emitter.emit (index.js:145)
at XHR.onPacket (transport.js:103)
at callback (polling.js:101)
at Array.forEach (<anonymous>)
at XHR.onData (polling.js:105)
at Request.<anonymous> (polling-xhr.js:94)
at Request.push.dMso.Emitter.emit (index.js:145)
at Request.onData (polling-xhr.js:236)
This is my Nginx configuration in /etc/nginx/sites-available/default:
server{
charset utf-8;
listen 80 default_server;
server_name 18.231.153.164;
# angular app & front-end files
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
root /opt/front-end/dist/admin;
try_files $uri /index.html;
}
# node api reverse proxy
location /api/ {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://localhost:4000/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# node api reverse proxy
location /socket.io {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://localhost:4000/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
As you can see, my node.js is running at port 4000, so everytime someone try to access the web site with the path /api/ it will be redirected to the node.js server.
Here is a piece of my node.js code:
const socketio = require('socket.io');
const express = require('express');
const app = express();
const port = 4000;
const httpServer = app.listen(port, () => {
console.log('Server listening on port ' + port);
});
let io = socketio(httpServer, {
cors: {
origin: "http://localhost:5200",
},
});
// auth moddleware
io.use((socket, next, err) => {
const jwtToken = socket.handshake.query.jwtToken;
// console.log('token --> ', jwtToken);
const user = socket.handshake.query.user;
if (!user) {return};
socket.user = JSON.parse(user);
next();
});
io.on('connection', (socket) => {
socket.emit('messageFromServer', {data: 'Welcome to server'});
})
Here is a piece of my front-end code:
import {io} from 'socket.io-client';
...
// Connect to server (When I am running locally I change '/api' to 'http://localhost:4000'
this.socket = io('/api', {secure: true, reconnection: true, rejectUnauthorized: false, query: {user: user, jwtToken: this.authService.authValue.jwtToken}});
// Listen to events
this.socket.on('usersOnline', (usersOnline) => {
console.log('Users online now:', usersOnline);
});
this.socket.on('connect_error', (err) => {
console.log('ERR::', err);
});
The version of socket.io in the server is "^4.0.0", and the version of the socket.io-client in front and is "^4.0.0".
I believe this issue is related with the reverse proxy and socket.io somehow. As I told before, the socket.io connection works fine in local envoriment.
Can someone please help me?
I found the solution.
I need to add proxy_redirect off; on the socket.io reverse proxy.
location /socket.io {
proxy_pass http://localhost:4000;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
Then I had another problem, in the font end I start to get an error or invalid namespace.
So I change the client connection to / instead od /api:
this.socket = io('/', {query: {user: user, jwtToken: this.authService.authValue.jwtToken}});
Just check and install same version of socket.io and socket.io-client

CORS issues with Express, Socket.io and Nginx

I have adapted a tutorial to get a simple Socket.io chat going in Node. It works when hosted locally, but after pushing it to a test server I can't get the socket connection to be accepted. Seems to be a cross-origin related matter, though I'm slightly confused about how to route things in Nginx also. Following the advice in the related questions hasn't helped.
Client script:
var socket = io.connect('http://localhost/socket.io');
Index.js:
const express = require('express');
const app = express();
const path = require('path');
const httpServer = require('http').createServer(app);
const io = require('socket.io')(httpServer, {
cors:true,
origins:["*"],
// origins:["http://xxx.xxx.xxx.xxx:8080"],
// transports: ['websocket'],
});
const views_path = (__dirname + '/views');
app.set('views',views_path);
app.use(express.static(__dirname + '/public'));
app.get('/', function(req,res){
console.log('render request received');
res.render('startPage.ejs');
});
io.sockets.on('connection', socket => {
console.log('connection received.')
socket.on('username', function(username) {
socket.username = username;
io.emit('is_online', socket.username);
});
//...
});
httpServer.listen(8080);
nginx sites-available:
server {
server_name campfire;
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/campfire/html;
index index.html index.htm index.nginx-debian.html;
location ^~ /assets/ {
gzip_static on;
expires 12h;
add_header Cache-Control public;
}
location / {
proxy_set_header Host $host;
#proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://localhost:8080;
}
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://localhost:8080/socket.io/;
}
}
Any insights welcome!
Hope this will help with all the CORS error
Because it will handle it for you
const cors = require('cors');
app.use(cors());
Docs CORS
Making this change fixed the issue:
Client script: var socket = io.connect();
This way uses the default connection destination with socket.

How to check is my reverse proxy server is working or not

Recently I had set up my reverse proxy server for my node js application rest api service with nginx server but how I know that proxy server is really working.
I'm doing like this
My node app rest api :
const fs = require('fs');
const https = require('https');
const express = require('express');
const app = express();
var router = express.Router();
router.get('/',function(req,res){
// console.log("Route = /");
res.json({"success" : 1})
});
app.use('/api/v2', router);
app.listen(8080);
which is running on server 1 with pvt ip address is APP_PRIVATE_IP_ADDRESS
My reverse proxy server config :
server {
listen 80;
server_name APP_PRIVATE_IP_ADDRESS;
location / {
proxy_pass http://APP_PRIVATE_IP_ADDRESS:8080;
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;
}
}

Error in socket.io connection - 'Session ID unknown'

I have an "Elastic Beanstalk" environment with the scalable server running 2 Ec2 instances.
On my root, I am serving angular 7 content using PHP API (using Codeigniter from API folder). I have socket.io chat module in my Node folder.
I am using Nginx to set up the Node and PHP project in a single EB environment.
I tried different options by modifying my Nginx .conf file as per some research but not able to fix the issue.
Here my Nginx .CONF setting file for SOCKET.IO.
server {
listen 80;
server_name sub.domain.com;
root /var/app/current/node;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_read_timeout 3600;
proxy_connect_timeout 3600;
proxy_redirect off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Port 443;
proxy_set_header Host $host;
}
}
My socket.io code.
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var port = 3000;
var socketController = require('./socketController.js')
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html');
});
var nsp = io.of('/namespace');
/**
* Socket for chat message
*/
io.on('connection', function (socket) {
socket.on('client_user_join', socketController.userJoin.bind(null, socket, nsp, io));
socket.on('client_send_chat_message', socketController.sendChatMessage.bind(null, socket, nsp, io));
socket.on('client_received_chat_message', socketController.receivedChatMessage.bind(null, socket, nsp, io));
socket.on('disconnect', socketController.disconnect.bind(null, socket));
});
http.listen(port, function () {
console.log('listening on *:' + port);
});
I am getting Session ID unknown at intial lever and after few minutes I am getting failed: Error during WebSocket handshake: Unexpected response code: 400
My socket connection link
https://sub.domain.com/socket.io/?EIO=3&transport=polling&t=Mtzwcpj&sid=TSMAaNI0KxDuzcIEAA4s
I already try following option.
Try to connect socket server using different transports.
this.socket = io('https://sub.domain.com/namespace', {transports: ['websocket']});
At the AWS side, enable Stickiness to 1 day.
I do not understand whether it blocking by Nginx configuration or I have to use Radis to fix this as I have two EC2 instances running.

Resources