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);
Related
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');
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
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 !
when i print client in console logconsole.log(client ${client}); it shows undefined.
I think i should do something in my client code but don't know what.
Server code -
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', function connection(ws, request, client) {
console.log(`client ${client}`);
ws.on('message', function message(msg) {
console.log(`Received message ${msg}`);
});
});
client code-
const Websocket = require('ws');
const ws = new Websocket('ws://localhost:8081');
function noop() {}
ws.on("message", function(event){
console.log(event);
});
const ping = function() {
ws.ping(noop);
}
setInterval(ping, 30000);
ws doesn't support client out of the box.
See: https://www.npmjs.com/package/ws#client-authentication
the gist of it is that you need to use an HTTP server to listen to any connections (not using ws to listen) and "manual" emit the connection event with additional data (like client).
I am quite new to this thing. I just wanted to know if it is possible to get the web sockets client side request header.
I'm using in the server side node.js:
Using ExpresJS I can get headers like:
router.post('/', function (req, res, next) {
console.log(req.headers);
});
Using Web Socket, its possible?
var WebSocket = require('ws');
var ws = new WebSocket('ws://www.host.com/path');
ws.on('open', function open() {
// how to get the headers
ws.send('something');
});
It is possible?
Thanks
WebSockets don't have headers, but their upgrade requests do.
var WebSocketServer = require('ws').Server
, wss = new WebSocketServer({ port: 8080 });
wss.on('connection', function connection(ws) {
console.log(ws.upgradeReq.headers);
ws.on('message', function incoming(message) {
console.log('received: %s', message);
});
ws.send('something');
});
Note you can't set headers as part of the ws request.