No response from websocket from my subdomain - node.js

I have a problem only in production mode, let me explain:
I created a subdomain on which I placed a websocket as follows:
const app = require("../app"); // app.js it's OK !
const server = require("http").createServer(app);
const WebSocket = require("ws");
const wss = new WebSocket.Server({ server });
wss.on("connection", (ws) => {
// Code is reduced for demo
console.log('New connection') // Is triggered by the client from my primary domain
ws.on("close", () => {
console.log(`Connection closed`);
});
});
server.listen()
I specify that the subdomain and the main domain are in https.
This is the client code on my main domain:
socket = new WebSocket('wss://my-subdomain.com/');
socket.addEventListener("open", () => {
console.log('Connection open'); // But it never fires
});
Does anyone know where the problem comes from? Thanks for your help !

Related

Express and Websocket to run on the same port on the same file

I'm running two apps that sends real-time messages to each other using websocket and also generate a random link using express.js, now i hosted the server with both react apps to my vps host and want to make the websocket connection secure (wss://) but i realize i'll have to get the express server on the same port too, so the ssl/tsl works for both - so how do i do that?
Here is my full code, all on the same file:
const webSocketServerPort = 8000;
const webSocketServer = require('websocket').server;
const http = require('http');
const server = http.createServer(); server.listen(webSocketServerPort); console.log('Listening on port 8000');
const wsServer = new webSocketServer({ httpServer: server })
//GEERTOOOO
const express = require('express'); const cors = require('cors'); const fs = require('fs'); const app = express();
app.use(cors({ origin: '*' }));
app.get('/', (req, res) => { // Generate a random 6-character string const linkId = Math.random().toString(36).substr(2, 6);
// Save the link in the lex.json file fs.readFile('lex.json', (err, data) => { if (err) { console.error(err); res.status(500).send('Error generating link'); return; }
const links = JSON.parse(data);
links[linkId] = {
destination: 'http://localhost:4000/',
expires: Date.now() + 1000 * 60 * 5 // expires in 5 minutes
};
fs.writeFile('lex.json', JSON.stringify(links), (err) => {
if (err) {
console.error(err);
res.status(500).send('Error generating link');
return;
}
// Send the link back to the client
res.send(`http://localhost:3000/${linkId}`);
});
}); });
app.get('/:linkId', (req, res) => {
fs.readFile('lex.json', (err, data) => {
if (err) { console.error(err); res.status(500).send('Error retrieving link');
return;
}
const links = JSON.parse(data);
const link = links[req.params.linkId];
if (!link) {
res.status(404).send('Link not found');
return;
}
// Check if the link has expired
if (link.expires < Date.now()) {
res.status(410).send('Link has expired');
return;
}
// Redirect to the destination
res.redirect(link.destination);
}); });
app.listen(3000, () => { console.log('Server listening on port 3000'); });
//GEERTOOOO
const clients = {};
const getUniqueID = () => { const s4 = () => Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
return s4() + s4() + '-' + s4(); }
wsServer.on('request', (request) => { var userID = getUniqueID();
const connection = request.accept(null, request.origin); clients[userID] = connection;
connection.on('message', (message) => {
if (message.type === 'utf8') {
for(var key in clients) {
if (clients[key] !== clients[userID]) {
clients[key].sendUTF(message.utf8Data);
console.log(`Sent Message to: ${clients[key]}`);
}
}
}
}) })
Note: the express server is on port 3000 and the websocket server runs on port 8000.
I,ve tried just changing the port to same thing but i get an error when trying to use the websocket server for messages.
THE PURPOSE OF ALL THIS IS JUST TO MAKE THE WEBSOCKET CONNECTION AND EXPRESS CONNECCTION SECURE SO MY APPS (with letsencrypt ssl) can connect to the servers
It is not possible to create two separate server instances, both listening on the same port. But, specifically for a webSocket, you can share one server instance between Express and the webSocket server code. This is possible because a webSocket connection always starts with an http request (thus it can be listened for using your Express http server. And, because these http requests that initiate a webSocket all contain identifying headers they can be separated out from the regular http requests for Express by looking at the headers. The webSocket server code already knows how to do that for you.
To do that, first capture the Express server instance:
const server = app.listen(3000, () => { console.log('Server listening on port 3000'); });
Then, use that server instance when you create your webSocket server.
const wsServer = new webSocketServer({ httpServer: server });
Then, remove this code because you don't want to create yet another http server instance for the webSocket server:
const server = http.createServer();
server.listen(webSocketServerPort);
console.log('Listening on port 8000');

Why i have no response from my websocket?

I need your help because i have a node js server with websocket like this :
const app = require("../app"); // Basic app file
const server = require("http").createServer(app);
const WebSocket = require("ws");
const wss = new WebSocket.Server({ server });
wss.on("connection", (ws) => {
ws.send('message')
ws.on("close", () => {
console.log('connection closed'));
});
ws.on("message", (data) => {
console.log(data.toString());
});
});
server.listen();
And client side :
var ws = new WebSocket('wss://topicsall.fr',)
ws.onopen = function () {
console.log('open');
};
ws.onmessage = function () {
console.log('message');
};
I have no error message but the connection remains on hold and is interrupted after the elapsed time.
In dev mode I have no problem, it's only in production.
I've been stuck for 4 days, I really need your help! Thanks

How to send websocket message to client from the serverside

Hello I have two backends laravel and Nodejs
and There will be one frontend.
So if the front end requests something on laravel and laravel requests to node and Node has to send a message to the client through WebSocket.
How to do It?
Index.js
const app = require('express')();
const http = require('http');
const WebSocket = require('ws')
//initialize a simple http server
const server = http.createServer(app);
app.get('/', function(req, res) {
res.sendFile(__dirname + '/index.html');
});
let sendNotification;
//initialize the WebSocket server instance
const wss = new WebSocket.Server({ server });
let socketapi = require('./socketapi')
socketapi.start(wss)
//start our server
server.listen(process.env.PORT || 5555, () => {
console.log(`Server started on port ${server.address().port} :)`);
});
socketapi.js
module.exports ={
start: (wss) => {
wss.on('connection', (ws) => {
console.log('connected!!!');
console.log(socketIds)
//connection is up, let's add a simple simple event
// triggerMessage('data');
ws.id=uuidv4()
ws.on('message', (message) => {
console.log('received: %s', message);
// ws.send(`Hello, you sent -> ${message}`);
});
}
}
}
Now I want to use this socket in the controller file and send it as I get a request.
When I export and import socket it logs as undefined.
I have stored and ws in array with particular Id and that Id was associated with data in DB so I can use that Id to get ws and send through that ws on function calling

Why does my websocket handshake fail with unexpected response 200?

I have seen this question several times, but I feel that my use case is not quite addressed, so I'm posting it below:
I get this error when trying to connect to my websocket:
scripts.js:44 WebSocket connection to 'ws://localhost:3000/' failed: Error during WebSocket handshake: Unexpected response code: 200
There's one small change that makes it fail versus succeed. See below:
Server.js:
'use strict';
const express = require('express');
const WebSocket = require('ws');
const PORT = process.env.PORT || 3000;
// Failing:
const server = express().use(express.static('public'));
server.get('/', function (req, res) {
res.sendFile(path.join(__dirname + '/public/index.html'));
});
server.listen(PORT, () => {
console.log(`Example app listening on PORT ${PORT}!`)
});
///
// Working (no websocket connection issues):
///const server = express().use(express.static('public'))
// .listen(PORT, () => {
// console.log(`Example app listening on PORT ${PORT}!`)
// });
const wss = new WebSocket.Server({ server });
wss.on('connection', function connection(ws) {
console.log(ws);
ws.on('message', function incoming(message) {
console.log('received message: %s', message);
wss.clients.forEach(function each(client) {
if (client !== ws && client.readyState === WebSocket.OPEN) {
client.send(message);
}
});
});
});
relevant: client code:
var HOST = location.origin.replace(/^http/, 'ws');
var socket = new WebSocket(HOST); //this is the line where the connection is attempted.
Running on localhost, ngrok, or deployed to heroku seems to make no difference, unless I missed something...
I have tried various things from other posts but to no avail. They mention changing networking configurations (doesn't seem relevant to my use), or various ways to configuring express js, but they don't help. It's really just that small change in the above code. Is the websocket hitting the GET route?

WebSockets: Reject handshake for wrong protocol used by client (nodejs)

I have a very basic websocket server / client in JS:
Server:
const WebSocket = require('ws');
const wss = new WebSocket.Server({port: 3300});
wss.on('connection', function connection(ws, req) {
});
Client:
var ws = new WebSocket('wss://example.com/socket', ['appProtocol']);
I want to reject the connection with the server when the Client is not using the
'appProtocol' protocol.
I feel like this should be pretty easy, still I cant find anything and cant get it done by myself. Any help is highly appreciated, thank you!
Nvm, I found a solution that works for me:
Server:
const WebSocket = require('ws');
const http = require('http');
const server = http.createServer();
const wss = new WebSocket.Server({noServer: true});
wss.on('connection', (ws, req) => {
console.log('Opened Connection with URL ' + req.url.substr(1));
ws.on('close', () => {
console.log('Closed Connection with URL ' + req.url.substr(1));
});
});
server.on('upgrade', (request, socket, head) => {
if (request.headers['sec-websocket-protocol'] === 'appProtocol') {
wss.handleUpgrade(request, socket, head, (ws) => {
wss.emit('connection', ws, request);
})
} else {
socket.destroy();
}
});
server.listen(3300);

Resources