Hello everyone,
I've got a problem after pushing both my NodedJs apps to my ubuntu server (serving sites in nginx with https). In my local environment with using localhost, the connections are established sucessfully, however after pushing to the server I get following response inside my second app (the admin) admin.domainname.com inside the client JavaScript console:
manager.js:108 WebSocket connection to 'wss://domainname.com/socket.io/?EIO=4&transport=websocket' failed
Heres the part where I establish the socket in my first app running on domainname.com and sending a message:
/*rest of app.js file with express.js*/
const PORT = 3000;
const server = app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`)
})
const socket = socketIo(server);
socket.on('connection', (socket) => {
console.log("connected")
socket.emit("testmessage", "Hello World")
socket.on('disconnect', () => {});
});
In the second app (admin.domainname.com) inside my client-side JavaScript I want to receive the message like so:
const socketdomainconstruct = () => {
if (location.port) {
return "http://localhost:3000"
} else {
return "https://domainname.com"
}
}
const socket = io(socketdomainconstruct(), { transports: ['websocket', 'polling', 'flashsocket']
socket.on("connect", () => {
console.log("connected");
socket.on("testmessage", (message) => {
console.log(message);
});
});
For explanation, when i use http://localhost:3000 inside above socket.io instance, I can connect sucessfully and everything works as espected, so no issues with the overall structure. Only once i switch to https I get the error, which i dont seem to understand, since nothing changed.
Potential Issues could lay in:
app.use((req, res, next) => {
res.removeHeader('Server');
res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0');
res.setHeader('Pragma', 'no-cache');
res.setHeader('Expires', '0');
res.setHeader('Last-Modified', new Date().toUTCString());
res.setHeader('Content-Security-Policy', "default-src 'self'; script-src 'self' 'unsafe-inline' cdn.socket.io code.jquery.com cdn.jsdelivr.net; style-src 'self' 'unsafe-inline'; img-src 'self' bing.com; connect-src 'self' *");
res.setHeader('Permission-Policy', 'accelerometer=(), camera=(), microphone=(), geolocation=(), gyroscope=()');
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('X-Content-Type-Options', 'nosniff');
res.setHeader('X-Frame-Options', 'deny');
res.setHeader('X-XSS-Protection', '1; mode=block');
res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
next();
});
I hope that someone can help me in clarifying / isolate the problem, or even solve it with me, for reference I will also include helpful links from Socket.io
Thanks in advance for any help and tips you can provide, this would be really helpful for me!
Cheers Raffael
The problem was fixed by first adding the correct cors option to the SocketIO server object:
socketIo(server, {cors: {origin: ["https://admin.domainname.com", "http://localhost:3000"]}}); // more than one origin can be incuded with array style writing...
See more in the docs on SocketIO:
Also I had to set up Nginx Proxy correctly, like so:
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://admin-container:4000; #localhost in case of not running the app inside a Docker container
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; #important part for Websocket connection to work
proxy_set_header Connection 'upgrade'; #important part for Websocket connection to work
proxy_cache_bypass $http_upgrade;
}
This can also be seen in the SocketIO docs, it is also duable for Apache and Caddy2 not only Nginx!
Overall this problem could have been prevented by correctly reading the docs, they are quite good, thanks for everybodys help, wish you a great day, and hopefully the problem solving may help other persons with similar problems
My setup was
Cheers Raffael