Running and ws servers on the same port

If, like me, you are migrating a Node.js WebSocket server application from to using the plain ws package, then you may want to use both packages at the same time, on the same port, during the upgrade, to allow for backwards compatibility during the upgrade.

The following code shows how this can be done:

const http = require('http');
const io = require('');
const ioc = require('');
const WebSocket = require('ws');

const httpServer = http.createServer();
const ioServer = io(httpServer);
const wsServer = new WebSocket.Server({ noServer: true });

const ioHandleUpgrade = httpServer._events.upgrade;
delete httpServer._events.upgrade;

httpServer.on('upgrade', function (req, socket, head) {
    if (req.url.indexOf('') > -1) {
        ioHandleUpgrade(req, socket, head);

    } else {
        wsServer.handleUpgrade(req, socket, head, (webSocket) => {
            wsServer.emit('connection', webSocket, req);

Here we replace the upgrade event handler added by to our HTTP server with a handler that inspects the URL and passes the request either to the original handler or to the ws server instance.

We can test that clients are routed correctly by adding some request handlers to our servers:

ioServer.on('connection', (socket) => {
    console.log(' client connected');

    socket.on('message', (data) => {
        console.log(' client message', data);

    socket.on('disconnect', () => {
        console.log(' client disconnected');

wsServer.on('connection', (socket) => {
    console.log('ws client connected');

    socket.on('message', (data) => {
        console.log('ws client message', data);

    socket.on('close', () => {
        console.log('ws client disconnected');

We can then start the server and send requests from and ws clients:

httpServer.on('listening', () => {
    const ioClient = ioc('ws://localhost:8080/');

    ioClient.on('connect', () => {
        setTimeout(() => ioClient.close(), 100);

    const wsClient = new WebSocket('ws://localhost:8080/');

    wsClient.on('open', () => {
        setTimeout(() => wsClient.close(), 100);

    setTimeout(() => httpServer.close(), 1000);


When we run our simple app we can see that messages are being correctly received by the relevant WebSocket servers:

$ node websocket.js client connected
ws client connected
ws client message foo client message foo
ws client disconnected client disconnected