ws

repository·master·Indexed 12 days ago

https://github.com/websockets/ws

A high-performance, thoroughly tested WebSocket client and server implementation for Node.js. Version 8.21.3 provides features such as permessage-deflate compression, stream integration via createWebSocketStream, and support for binary data. It allows for flexible server configuration, including attaching to existing HTTP/S servers or using 'noServer' mode for manual upgrade handling and client authentication.

Tokens
10.1K
Snippets
24
Records
43
Agent score
97%

What's inside ws

  1. WebSocket Ready State Constants

    master

    The readyState property of a WebSocket instance indicates the current state of the connection. Use these constants to check if a connection is ready for communication:

    • CONNECTING (0): The connection is not yet open.
    • OPEN (1): The connection is open and ready to communicate.
    • CLOSING (2): The connection is in the process of closing.
    • CLOSED (3): The connection is closed.
  2. Configure WebSocket compression (permessage-deflate)

    master

    The permessage-deflate extension enables compression for WebSocket messages. It is enabled by default on the client and disabled by default on the server.

    Warning: Compression adds significant memory and performance overhead. On Linux, high concurrency with compression can lead to memory fragmentation in Node.js/zlib. Use with caution in production.

    To disable compression on the client, set perMessageDeflate: false in the constructor options.

    import WebSocket, { WebSocketServer } from 'ws';
    
    const wss = new WebSocketServer({
      port: 8080,
      perMessageDeflate: {
        zlibDeflateOptions: {
          chunkSize: 1024,
          memLevel: 7,
          level: 3
        },
        zlibInflateOptions: {
          chunkSize: 10 * 1024
        },
        clientNoContextTakeover: true,
        serverNoContextTakeover: true,
        serverMaxWindowBits: 10,
        concurrencyLimit: 10,
        threshold: 1024
      }
    });
  3. Opt-in for performance with bufferutil

    master

    To improve the performance of masking and unmasking WebSocket frame payloads, you can install the optional bufferutil binary addon. Prebuilt binaries are available for most platforms.

    To force ws to NOT use bufferutil, set the WS_NO_BUFFER_UTIL environment variable.

    npm install --save-optional bufferutil
  4. Get the client IP address

    master

    To obtain the remote IP address of a connecting client, access the remoteAddress property from the raw socket attached to the req (request) object in the connection event.

    If your server is running behind a proxy (such as NGINX), the client's IP is typically provided in the X-Forwarded-For header. You should parse this header to retrieve the original client IP.

    import { WebSocketServer } from 'ws';
    
    const wss = new WebSocketServer({ port: 8080 });
    
    // Direct access via raw socket
    wss.on('connection', function connection(ws, req) {
      const ip = req.socket.remoteAddress;
      ws.on('error', console.error);
    });
    
    // Access via proxy header (e.g., NGINX)
    wss.on('connection', function connection(ws, req) {
      const ip = req.headers['x-forwarded-for'].split(',')[0].trim();
      ws.on('error', console.error);
    });
  5. Handle HTTP upgrades manually in noServer mode

    master

    When using noServer: true, you must manually call server.handleUpgrade() to upgrade an HTTP request to a WebSocket connection.

    Method Signature: server.handleUpgrade(request, socket, head, callback)

    • request {http.IncomingMessage}: The client HTTP GET request.
    • socket {stream.Duplex}: The network socket.
    • head {Buffer}: The first packet of the upgraded stream.
    • callback {Function}: Called with (websocket, request) upon success.

    Example:

    const { WebSocketServer } = require('ws');
    const http = require('http');
    
    const server = http.createServer((req, res) => {
      res.writeHead(404);
      res.end();
    });
    
    const wss = new WebSocketServer({ noServer: true });
    
    server.on('upgrade', (req, socket, head) => {
      if (wss.shouldHandle(req)) {
        wss.handleUpgrade(req, socket, head, (ws) => {
          ws.on('message', (msg) => console.log('Received:', msg));
        });
      } else {
        socket.destroy();
      }
    });
    
    server.listen(8080);
    server.handleUpgrade(request, socket, head, (websocket, request) => {
      // websocket is the new WebSocket instance
      // request is the original http.IncomingMessage
    });
  6. Opt-in for performance with utf-8-validate

    master

    For Node.js versions prior to v18.14.0, you can install utf-8-validate to provide a binary polyfill for buffer.isUtf8().

    To force ws to NOT use utf-8-validate, set the WS_NO_UTF_8_VALIDATE environment variable.

    npm install --save-optional utf-8-validate
  7. Connect to IPC endpoints via WebSocket

    master

    The ws library supports Inter-Process Communication (IPC) connections using specific URL formats.

    On Unices:

    ws+unix:/absolute/path/to/uds_socket:/pathname?search_params

    On Windows:

    ws+unix:\\.\\pipe\\pipe_name:/pathname?search_params

    Note: The : character separates the IPC path from the URL path. If the URL path is omitted, it defaults to /.

  8. Configure optional dependencies via environment variables

    master

    You can control whether ws attempts to use certain optional performance-enhancing dependencies by setting the following environment variables to any non-empty value:

    • WS_NO_BUFFER_UTIL: Prevents the bufferutil dependency from being required.
    • WS_NO_UTF_8_VALIDATE: Prevents the utf-8-validate dependency from being required.
    # Example: Running without bufferutil and utf-8-validate
    WS_NO_BUFFER_UTIL=1 WS_NO_UTF_8_VALIDATE=1 node app.js
  9. Configure permessage-deflate compression

    master

    To enable compression, set perMessageDeflate to true or provide an object with specific parameters:

    • serverNoContextTakeover {Boolean}: Whether to use context takeover.
    • clientNoContextTakeover {Boolean}: Acknowledge disabling of client context takeover.
    • serverMaxWindowBits {Number}: The value of windowBits.
    • clientMaxWindowBits {Number}: Request a custom client window size.
    • zlibDeflateOptions {Object}: Options to pass to zlib on deflate.
    • zlibInflateOptions {Object}: Options to pass to zlib on inflate.
    • threshold {Number}: Payloads smaller than this (default 1024) won't be compressed if context takeover is disabled.
    • concurrencyLimit {Number}: Number of concurrent zlib calls (default 10).
  10. How permessage-deflate negotiation works

    master

    The PerMessageDeflate class manages the handshake process for the compression extension through offer() and accept() methods.

    1. Offering: A peer calls offer() to generate an object containing its preferred compression parameters (e.g., server_no_context_takeover, client_max_window_bits).
    2. Accepting: The receiving peer calls accept(configurations) with the offered parameters. This method normalizes the parameters and determines the final accepted configuration based on the local instance's constraints.

    Negotiation Flow

    • Server side: The server uses acceptAsServer to compare the client's offer against its own options. It will reject offers that violate its local constraints (like a requested window size larger than allowed).
    • Client side: The client uses acceptAsClient to process the server's response. It validates that the server's response does not conflict with the client's initial requirements.

    If no compatible configuration can be found during accept(), an error is thrown.

  11. Configure WebSocketServer options

    master

    When instantiating new WebSocketServer(options), you can tune several parameters:

    OptionTypeDefaultDescription
    allowSynchronousEventsBooleantrueIf false, improves WHATWG compatibility but may impact performance.
    autoPongBooleantrueAutomatically sends a pong in response to a ping.
    backlogNumber-Max length of the queue of pending connections.
    clientTrackingBoolean-If true, the server maintains a clients Set of all connected clients.
    closeTimeoutNumber30000Milliseconds to wait for a graceful close before forcing termination.
    handleProtocolsFunction-Function to handle WebSocket subprotocols.
    hostString-Hostname to bind the server.
    maxBufferedChunksNumber262144Max number of buffered data chunks (0 to disable).
    maxFragmentsNumber16384Max number of fragments in a message (0 to disable).
    maxPayloadNumber104857600Max allowed message size in bytes (0 to disable).
    noServerBoolean-Enables no server mode.
    pathString-Only accept connections matching this path.
    perMessageDeflateBoolean|ObjectfalseEnable/disable permessage-deflate extension.
    portNumber-Port to bind the server.
    serverhttp.Server|https.Server-A pre-created Node.js HTTP/S server.
    skipUTF8ValidationBooleanfalseSkips UTF-8 validation (use only with trusted clients).
    verifyClientFunction-Function to validate incoming connections (discouraged).
    WebSocketFunctionWebSocketCustom WebSocket class to use.