简体   繁体   中英

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');

You generally cannot have two different services listening on the same port (see this question for more information on this).

There are a few options for what you can do next. One option would be to run a service on a protected port that takes requests to both of your other services, and then redirects them to those ports (acting as a proxy). Another option would be to protect both ports, possibly via a different method if this is too difficult currently. A third option is to move all your different endpoints into a single service, though this might not be sensible from an architecture perspective.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM