I deployed a React.js PWA application (frontend) and a NodeJS backend in a server. Both are working well with Nginx and PM2. I created a WebSocket in my backend server to connect with my Frontend, but I’ve never worked with this before. In localhost, it worked fine, but when I deployed it to my server, my connection started and finished repeatedly.
Here is my configuration in NodeJS:
const clients = new Map();
exports.setupWebSocket = (server) => {
const wss = new WebSocket.Server({ server });
wss.on("connection", (ws, req) => {
const cookie = decodeURIComponent(req.headers.cookie);
const startTokenIndex = cookie.indexOf("token=") + "token=".length;
const endTokenIndex = cookie.indexOf(";");
const tokenData = cookie.substring(startTokenIndex, endTokenIndex);
// Extract the token information
const decodedToken = decodeURIComponent(tokenData);
const parsedToken = JSON.parse(decodedToken);
// Use the user ID
const userId = parsedToken._id;
if (!clients.has(userId)) {
clients.set(userId, new Set());
}
clients.get(userId).add(ws);
ws.on("close", () => {
const userSet = clients.get(userId);
if (userSet) {
userSet.delete(ws); // Remove specific WebSocket connection
if (userSet.size === 0) {
clients.delete(userId); // Remove the user if no connections left
}
}
});
});
};
In my app.js file, I am exporting this function to my server.js:
const express = require("express");
const cors = require("cors");
const config = require("./config/server");
const swaggerUi = require("swagger-ui-express");
const swaggerOutput = require("./doc/swagger.json");
const { setupWebSocket } = require("./controllers/log");
const app = express();
app.use(cors(config.cors.corsOption));
app.use((req, res, next) => {
res.header(
"Access-Control-Allow-Headers",
"x-access-token, Origin, Content-Type, Accept"
);
next();
});
app.use(express.json({ limit: "50mb" }));
app.use(express.urlencoded({ limit: "50mb", extended: false }));
app.use("/doc", swaggerUi.serve, swaggerUi.setup(swaggerOutput));
app.get("/", (req, res) => {
res.send("Welcome");
});
module.exports = {
app,
setupWebSocket,
};
And, finally, in my server.js:
const { app, setupWebSocket } = require("../app");
const config = require("../config/server");
const http = require("http");
const server = http.createServer(app);
// Configure the websocket
setupWebSocket(server);
module.exports = (err) => {
if (err) {
console.log("Error connecting to the DB");
console.log(err);
}
server.listen(process.env.PORT || config.app.port, (err) => {
if (err) {
console.log(err);
}
console.log(`Starts in ${config.app.url}:${process.env.PORT || config.app.port}`);
});
};
My nginx conf.d file is configured as bellow:
server {
server_name subdomain.domain.com;
location / {
proxy_pass http://MYIP:MYPORT;
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;
}
# SSL CONFIG
listen 443 ssl http2;
ssl_certificate /etc/ssl/cert.crt;
ssl_certificate_key /etc/ssl/cert.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
}
Lastly, in my react app, I am trying to establish this connection as follows:
const ws = new ReconnectingWebSocket(
`wss://${process.env.REACT_APP_DOMAIN}`
);
ws.onopen = () => {
console.log("WebSocket connected");
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
};
ws.onclose = () => {
console.log("WebSocket disconnected");
};
ws.onerror = (error) => {
console.error("Error:", error);
};
It is remembered that process.env.REACT_APP_DOMAIN
is being correctly read and its value is http://MYIP:MYPORT
.
After starting my app, as stated before, the console logs “connected” and “disconnected” immediately after the connection establishment. Besides, no error occurs after the connection, it just disconnects without messages.
Does anyone know what I’m doing wrong?