Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Express and WebSocket listening on the same port

I have an app.js which is used to trigger two events when some POST data are received:

  1. Insert POST data into a database
  2. Send a message to a client using a WebSocket

Here is the app.js (only the important lines)

var express = require('express'); var bodyParser = require('body-parser'); var server = require('./server');  var app = express(); var port = process.env.PORT || 3000;  app.post('/server', server);  app.listen(port, function(){   console.log('Slack bot listening'); }); 

And here is the server.js (only the important lines)

var db = require('./DB'); var WebSocketServer = require('ws').Server;  var insertData = function(req, res){      var wss = new WebSocketServer({server: server});     console.log('WebSocketServer created');     wss.on('connection', function(wss){         wss.send(JSON.stringify('Socket open'));     });     wss.on('close', function(){         console.log('WebServerSocket has been closed');     }); };  module.exports = insertData; 

What I would like to achieve is to set the WebSocketServer in a way that it listen to the same port of the app. I thought about passing the server var from app.js to server.js but

  1. I think this a not an elegant way to do it
  2. I don't know how to do it

What do you guys think?

like image 212
Mornor Avatar asked Jan 15 '16 10:01

Mornor


People also ask

Can a Socket.IO and express on same port?

On Scalingo, your application must listen to the port defined in the PORT environment variable dynamically defined by the platform.

Can HTTP and WebSocket use same port?

Yes it can run on the same port, in fact it must run on the same port; the raison d'etre of websocket handshake is so that the websocket can run on the same connection without confusing intermediaries that doesn't understand websocket.

Does express support WebSockets?

WebSocket endpoints for Express applications. Lets you define WebSocket endpoints like any other type of route, and applies regular Express middleware. The WebSocket support is implemented with the help of the ws library.

Can WebSockets send and receive at the same time?

The key word in that definition is two-way: with WebSocket, both the client and the server can trigger communication with one another, and both can send messages, at the same time.


1 Answers

Based on your code and comments, here's a super simple example of how it would work together.

First, the http-server.js - a typical express app, except that we do not start the server with app.listen():

'use strict';  let fs = require('fs'); let express = require('express'); let app = express(); let bodyParser = require('body-parser');  app.use(bodyParser.json());  // Let's create the regular HTTP request and response app.get('/', function(req, res) {    console.log('Get index');   fs.createReadStream('./index.html')   .pipe(res); });  app.post('/', function(req, res) {    let message = req.body.message;   console.log('Regular POST message: ', message);   return res.json({      answer: 42   }); });  module.exports = app; 

Now, the ws-server.js example, where we create the WSS server from a node native http.createServer(). Now, note that this is where we import the app, and give this native http.createServer the app instance to use.

Start the app with PORT=8080 node ws-server.js :

(Note you're launching the second, socket related, file (ws-server) not the first, http related, file (http-server).)

'use strict';  let WSServer = require('ws').Server; let server = require('http').createServer(); let app = require('./http-server');  // Create web socket server on top of a regular http server let wss = new WSServer({    server: server });  // Also mount the app here server.on('request', app);  wss.on('connection', function connection(ws) {     ws.on('message', function incoming(message) {          console.log(`received: ${message}`);          ws.send(JSON.stringify({        answer: 42     }));   }); });   server.listen(process.env.PORT, function() {    console.log(`http/ws server listening on ${process.env.PORT}`); }); 

Finally, this sample index.html will work by creating both a POST and a Socket "request" and display the response:

<html> <head>   <title>WS example</title> </head>  <body>   <h2>Socket message response: </h2>   <pre id="response"></pre>   <hr/>   <h2>POST message response: </h2>   <pre id="post-response"></pre>   <script>    // Extremely simplified here, no error handling or anything document.body.onload = function() {      'use strict';    // First the socket requesta   function socketExample() {     console.log('Creating socket');     let socket = new WebSocket('ws://localhost:8080/');     socket.onopen = function() {        console.log('Socket open.');       socket.send(JSON.stringify({message: 'What is the meaning of life, the universe and everything?'}));       console.log('Message sent.')     };     socket.onmessage = function(message) {        console.log('Socket server message', message);       let data = JSON.parse(message.data);       document.getElementById('response').innerHTML = JSON.stringify(data, null, 2);     };   }    // Now the simple POST demo   function postExample() {      console.log('Creating regular POST message');        fetch('/', {         method: 'post',         headers: {           "Content-type": "application/json"         },         body: JSON.stringify({message: 'What is the meaning of post-life, the universe and everything?'})       })     .then(response => response.json())       .then(function (data) {              console.log('POST response:', data);       document.getElementById('post-response').innerHTML = JSON.stringify(data, null, 2);        })       .catch(function (error) {         console.log('Request failed', error);       });      }    // Call them both;    socketExample();   postExample(); }   </script> </body> </html> 

Note you'll need a quite recent browser, one that has both WebSocket and fetch APIs for this client side part, but it's irrelevant anyway, it just gives you the gist of it.

like image 53
Zlatko Avatar answered Sep 21 '22 22:09

Zlatko