node.jswebsocket

Integrating websockets with a standard http.Server


I have a simple webserver like

var http = require('http'),
    url = require('url');
var server = http.createServer(function (req, res) {
  var uri = url.parse(req.url).pathname;
  if (uri == '/') {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
    return;
  }

  res.writeHead(404, {'Content-Type': 'text/plain'});
  res.end('File not found');
});
server.listen(0, '127.0.0.1');

I would now like to connect a single path (say, /ws) to a websocket, but leave the rest of the server unmodified.

However, ws seems to require me to set up a dedicated server (with everything that that entails, like SSL termination, security configuration, and port allocation).

How can I terminate just the path /ws to a websocket implementation?


Solution

  • I would recommend using the websocket package, it is a

    Websocket Client & Server Library implementing the WebSocket protocol as specified in RFC 6455.

    Which is what I wanted so it's why I use it. It's incredibly painless to use and I'm actually doing both wss and ws connections to node.js from html clients using pure javascript websockets.

    The git project is active, when I've posted issues I've had a response on the same day. An example from the link above shows how simple it is:

    var WebSocketServer = require('websocket').server;
    var http = require('http');
    
    var server = http.createServer(function(request, response) {
        console.log((new Date()) + ' Received request for ' + request.url);
        response.writeHead(404);
        response.end();
    });
    server.listen(8080, function() {
        console.log((new Date()) + ' Server is listening on port 8080');
    });
    
    wsServer = new WebSocketServer({
        httpServer: server,
        autoAcceptConnections: false
    });
    
    function originIsAllowed(origin) {
      // put logic here to detect whether the specified origin is allowed.
      return true;
    }
    
    wsServer.on('request', function(request) {
        if (!originIsAllowed(request.origin)) {
          // Make sure we only accept requests from an allowed origin
          request.reject();
          console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.');
          return;
        }
    
        var connection = request.accept('echo-protocol', request.origin);
        console.log((new Date()) + ' Connection accepted.');
        connection.on('message', function(message) {
            if (message.type === 'utf8') {
                console.log('Received Message: ' + message.utf8Data);
                connection.sendUTF(message.utf8Data);
            }
            else if (message.type === 'binary') {
                console.log('Received Binary Message of ' + message.binaryData.length + ' bytes');
                connection.sendBytes(message.binaryData);
            }
        });
        connection.on('close', function(reasonCode, description) {
            console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
        });
    });
    

    I should note, however, that the subprotocols is not obvious, as there is no example. There are some questions on the git site for the project that lead you in the right direction though.