Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

@clusterws/cws

ClusterWS510MIT3.0.0TypeScript support: included

cWS - fast C++ WebSocket implementation for Node.js

tiny, websocket, clusterws, socket, cws

readme

ClusterWS/cWS

Fast WebSocket implementation for Node.js

npm version travis build

Important Notes

Supported Node Versions

CWS Version Node 10 Node 11 Node 12 Node 13 Node 14
3.0.0 >=10.0 X >=12.16 >=13.9 >=14.5
2.0.0 >=10.0 X >=12.16 >=13.9 X
1.6.0 >=10.0 >=11.0 >=12.0 & <12.16 >=13.9 X

Documentation

Table of Contents

Installation

npm i @clusterws/cws

Websocket Client

Typings: dist/client.d.ts

Import cws WebSocket:

const { WebSocket } = require('@clusterws/cws');

Connect to WebSocket server:

const socket = new WebSocket(/* ws server endpoint **/);

Event on open is triggered when server accepts connection and this connection is ready to perform other actions:

socket.on('open', () => { });
// or like browser interface
socket.onopen = () => { };

Event on error is triggered if there is an error with the connection:

socket.on('error', (err) => { });
// or like browser interface
socket.onerror = (err) => { };

Event on close is triggered when connection has been closed:

// code: number and reason: string are optional
socket.on('close', (code, reason) => { });
// or like browser interface
socket.onclose = (code, reason) => { };

Event on message is triggered when client receives message(s):

// receives string or binary

socket.on('message', (message) => { });
// or like browser interface
socket.onmessage = (message) => { };

Event ping is triggered when other side sends ping to check if connection still active:

socket.on('ping', () => { });

Event pong is triggered after ping has been sent and it received back conformation:

socket.on('pong', () => { })

To send message use send function:

// send accepts string or binary
// will automatically identify type
socket.send(msg);

// will overwrite/specify message type to string (does not transform data to specified type)
socket.send(msg, { binary: false });

// will overwrite/specify message type to binary (does not transform data to specified type)
socket.send(msg, { binary: true });

// will call callback after message sent or errored
socket.send(msg, null, (err) => { });

To close connection you can use close or terminate methods:

// clean close code and reason are optional
socket.close(code, reason);
// destroy socket 
socket.terminate()

Use ping function to manually send ping:

socket.ping();
// now just wait for `pong` event

To get current socket ready state can use readyState getter:

socket.readyState; // -> OPEN (1) or CLOSED (3)

// check if socket open can be done by
if(socket.readyState === socket.OPEN) {}

// check if socket closed can be done by
if(socket.readyState === socket.CLOSED) {}

To get addresses use _socket getter:

socket._socket;

// Returns some thing like (all fields could be undefined):
// {
//  remotePort,
//  remoteAddress,
//  remoteFamily
// }

For more information check typings (*.d.ts) files in dist folder

Websocket Server

Typings: dist/server.d.ts

Import cws WebSocket:

const { WebSocket } = require('@clusterws/cws');

Create WebSocket server:

const wsServer = new WebSocket.Server({ 
  /**
   * port?: number (creates server and listens on provided port)
   * host?: string (provide host if necessary with port)
   * path?: string (url at which accept ws connections)
   * server?: server (provide already existing server)
   * noDelay?: boolean (set socket no delay)
   * noServer?: boolean (use this when upgrade done outside of cws)
   * maxPayload?: number 
   * perMessageDeflate?: boolean | { serverNoContextTakeover: boolean;}
   * verifyClient?: (info: ConnectionInfo, next: VerifyClientNext) => void (use to allow or decline connections)
   **/ 
 }, () => {
  // callback called when server is ready
  // is not called when `noServer: true` or `server` is provided
  // from outside
});

Event on connection is triggered when new client is connected to the server:

// `ws` is websocket client all available options 
// can be found in `Websocket Client` section above
// `req` is http upgrade request
wsServer.on('connection', (ws, req) => {})

Event on error is triggered when server has some issues and noServer is false:

// on error event will NOT include httpServer errors IF
// server was passed under server parameter { server: httpServer },
// you can register on 'error' listener directly on passed server
wsServer.on('error', (err) => { })

Event on close is triggered after you call wsServer.close() function, if cb is provided both cb and on close listener will be triggered:

wsServer.on('close', () => { })

To get all connected clients use clients getter:

wsServer.clients;

// loop thought all clients:
wsServer.clients.forEach((ws) => { });

// get number of clients:
wsServer.clients.length;

To send message to all connected clients use broadcast method:

// broadcast string
wsServer.broadcast(message);

// broadcast binary
wsServer.broadcast(message, { binary: true });

cWS supports auto ping with startAutoPing function:

wsServer.startAutoPing(interval, appLevel);

// send ping to each client every 10s and destroy client if no pong received 
wsServer.startAutoPing(10000);

// pass true as second parameter to run app level ping
// this is mainly used for browser to track pings at client level
// as they do not expose on ping listener 
// look for browser client side implementation at the bottom
// `Handle App Level Ping In Browser (example)`
wsServer.startAutoPing(10000, true);

To stop server use close function:

wsServer.close(() => {
  // triggered after server has been stopped
})

handleUpgrade is function which is commonly used together with noServer (same as ws module)

const wss = new WebSocket.Server({ noServer: true });
const server = http.createServer();

wss.on('connection', (ws, req) => { })

server.on('upgrade', (request, socket, head) => {
  wss.handleUpgrade(request, socket, head, (ws) => {
      wss.emit('connection', ws, request);
  });
});

For more information check typings (*.d.ts) files in dist folder

Secure WebSocket

You can use wss:// with cws by providing https server to cws and setting secureProtocol on https options:

const { readFileSync } = require('fs');
const { createServer }  = require('https');
const { WebSocket, secureProtocol  } = require('@clusterws/cws');

const options = {
  key: readFileSync(/** path to key */),
  cert: readFileSync(/** path to certificate */),
  secureProtocol
  // ...other Node HTTPS options
};

const server = createServer(options);
const wsServer = new WebSocket.Server({ server });
// your secure ws is ready (do your usual things)

server.listen(port, () => {
  console.log('Server is running');
})

For more detail example check examples folder

Handle App Level Ping In Browser (example)

Handling custom App level ping, pong from the client side which does not have onping and onpong listeners available such as browsers.

Note if all your clients have onping and onpong listeners do not send appLevelPing ping from the server. If you enable appLevelPing you will need to implement similar handler for every client library which connects to the server.

const PING = 57;
const PONG = new Uint8Array(['A'.charCodeAt()]);

socket.binaryType = 'arraybuffer';

socket.onmessage = function (message) {
    // note actually sent message in
    // browser default WebSocket is under `message.data`

    // check if message is not string 
    if (typeof message.data !== 'string') {
        // transform it to Uint8Array
        let buffer = new Uint8Array(message.data);

        // Check if it is actually ping from the server
        if (buffer.length === 1 && buffer[0] === PING) {
            // this is definitely `ping` event you can call custom on ping handler 
            // also must send back immediately pong to the server 
            // otherwise server will disconnect this client
            return socket.send(PONG);
        }
    }

    // process with your logic
}

changelog

Released 2.0.0

Changes

  • Drop support for Node 8,9,11
  • Fix issues with latest Node 12
  • Add "Supported Node Versions" section in README

Released 1.6.0

Changes

  • If no close code provided from client return 1005 (similar to ws.js module)

Bugs

Released 1.5.0

Changes

  • Fix SSL support on Node 13.9+ #37
  • Abort connection on invalid Sec-WebSocket-Key header #35

Released 1.4.0

Changes

  • Return secureProtocol to docs (stick with tls 1.2)
  • Downgrade multiple listeners error to warning (allow listeners overwrite)

Released 1.3.1

Improvement

  • Remove secureProtocol from required options on ssl

Released 1.3.0

Improvement

  • Add SSL support to node 10,11,12,13 (outstanding issue with node 13.9.0 use 13.8.0 instead)

Released 1.2.0

Improvement

  • Do not register httpServer on error event if server has been passed from the user

Released 1.1.2

Fixes

  • Fix typings for on connection event

Released 1.1.0

Improvement

  • Added support for on close event on the WebSocketServer

Fixes

  • Validation prints warning if listener is not supported

Released 1.0.0

This is quite a big release with some important changes, improvement and fixes including but not limited to:

Improvement

  • Added noServer config
  • Added clients getter to WebSocketServer
  • Added handleUpgrade similar to ws module
  • Changed values of OPEN and CLOSED on WebSocket to 1 and 3 respectively
  • Reexported WebSocketServer under WebSocket.Server

Fixes

  • Fixed perMessageDeflate configuration
  • Fixed close code on fuzzing

Removed

  • Removed global.cws config
  • Removed websocket.remoteAddress as can get data from websocket._socket.remoteAddress or req.connection.remoteAddress
  • No more listening event emitted from WebSocketServer (can be implemented using callback)

Many other fixes and improvements...

Release 0.17.0

  • Remove support for SSL from Node.js 10+ (use proxy instead like nginx)
  • Added support for Node.js 13

Release 0.16.0

  • Improved typings for on('connection') handler #25
  • Improved typings for verifyClient #24
  • On verifyClient fail by default return code 401 #24

Release 0.15.0

Improvements

  • socket.send(buffer, { binary: false }) will force text opCode

Release 0.14.0

Improvements

  • Adjust verifyClient to return the same info object as ws module instead of headers return origin as headers can be accessed from req

Release 0.13.0

Improvements

  • Add support for node 12

Release 0.12.2

Improvements

  • Re throw error from cWS bindings.