@teamwork/websocket-json-stream

2.0.0 • Public • Published

WebSocketJSONStream

npm version Build Status Coverage Status

A nodejs stream wrapper for WebSocket connections. It works with browser WebSockets too.

Usage

const WebSocket = require('ws')
const WebSocketJSONStream = require('@teamwork/websocket-json-stream')

const stream = new WebSocketJSONStream(new WebSocket(url))
// ...

new WebSocket.Server({ server }).on('connection', ws => {
    const stream = new WebSocketJSONStream(ws)
    // ...
})

See example.js for a working usage example.

Error Handling

WebSocket error events are not handled by this module, so you should handle them yourself to avoid crashing the process unnecessarily in nodejs.

When writing to a stream when its associated WebSocket is already CLOSING or CLOSED, the stream emits an error event with the name property value equal to Error [ERR_CLOSED].

Closing a WebSocket via its stream

Calling stream.end() or stream.destroy() will close the WebSocket connection.

When a WebSocket is closed either by the server or the client, a CloseEvent will be emitted. CloseEvents have both a numeric code and a string reason property that may be used to indicate the type of closure.

stream.end()

Calling stream.end() will close the WebSocket with the code 1000 and reason 'stream end'. 1000 indicates a normal closure, meaning that the purpose for which the connection was established has been fulfilled. (https://tools.ietf.org/html/rfc6455#section-7.4.1)

Clients may implement this to mean that the server is closing the stream intentionally, and the client should not automatically reconnect.

const stream = new WebSocketJSONStream(ws)
// Closes WebSocket with the code 1000 and the reason 'stream end'
stream.end()

The code 1000 may also be used when calling the webSocket.close(code) method of WebSockets in browsers.

stream.destroy()

Calling stream.destroy() without an error object will close the stream without a code. This results in the client emitting a CloseEvent that has code 1005 and reason ''. 1005 is a reserved value and MUST NOT be set as a status code in a Close control frame by an endpoint. It is designated for use in applications expecting a status code to indicate that no status code was actually present. (https://tools.ietf.org/html/rfc6455#section-7.4.1)

const stream = new WebSocketJSONStream(ws)
// Closes WebSocket with no status code (1005) and the reason ''
stream.destroy()

Calling webSocket.close() method of WebSockets in browsers without any arguments will produce a CloseEvent with the code 1005. A reason string cannot be provided together with the code 1005.

stream.destroy(error)

Calling stream.destroy(error) with an error will emit an 'error' event and close the stream with the code 1011 and reason 'stream error' by default. 1011 indicates that a remote endpoint is terminating the connection because it encountered an unexpected condition that prevented it from fulfilling the request. (http://www.rfc-editor.org/errata_search.php?eid=3227)

const stream = new WebSocketJSONStream(ws)
stream.on('error', (error) => {
  // Error event must be handled, or it will be throw when calling
  // stream.destroy() with an error argument
})

// Closes WebSocket with the code 1011 and the reason 'stream error'
const error = new Error('Unexpected server error')
stream.destroy(error)

The code 1011 cannot be used when calling the webSocket.close(code) method of WebSockets in browsers.

error.closeCode and error.closeReason

Custom close code and reason values may be sent by setting error.closeCode or error.closeReason properties on the error argument passed to stream.destroy(error). For example:

const stream = new WebSocketJSONStream(ws)
stream.on('error', (error) => {
  // Error event must be handled, or it will be throw when calling
  // stream.destroy() with an error argument
})

// Example of extending from Error and adding additional properties
class CustomStreamError extends Error {
    constructor(message) {
        super(message)
        this.name = this.constructor.name
        Error.captureStackTrace(this, this.constructor)
        this.closeCode = null
        this.closeReason = null
    }
}

// Closes WebSocket with the code 4000 and the reason 'custom reason'.
// error.message is not sent to the client
const error = new CustomStreamError('Example error')
error.closeCode = 4000
error.closeReason = 'custom reason'
stream.destroy(error)

Browser WebSockets allow custom close codes between 3000 and 4999.

Dependencies (0)

    Dev Dependencies (6)

    Package Sidebar

    Install

    npm i @teamwork/websocket-json-stream

    Weekly Downloads

    1,302

    Version

    2.0.0

    License

    MIT

    Unpacked Size

    40.1 kB

    Total Files

    10

    Last publish

    Collaborators

    • irltopper
    • lisa-kavs
    • loaymoolb
    • furqanali
    • mari_ka
    • mattgeek
    • nern-tw
    • joseluis-tw
    • ivnosing
    • karenhodgins
    • ryanoc8
    • laurenoc125
    • karolina.truszkowska
    • alifletch
    • imrafalman
    • encarnaamoros
    • marcos.gutierrez
    • tonisanta
    • gmc123
    • rodynnz
    • tanyairwinblack
    • pmgriffin
    • victoriasloan
    • a1d0
    • alvarotw
    • seanogdev
    • conor.quin
    • manucuestatw
    • chrisrollins65
    • andrssl
    • kclaur
    • yonson2
    • xlerida
    • pktw
    • decob
    • pinkkis
    • ilserodriguez
    • k823
    • crssn
    • chrisjtwomey
    • simonbb
    • vg500
    • ma-jerez
    • ivayloovcharov
    • ismaelpenalver
    • kadenn
    • nathanmcclelland
    • fatihunlu
    • lmcaree
    • mjteamwork
    • matteobandiera
    • stdiopt
    • roryok
    • duncan1a
    • garycremen
    • dommurphytw
    • bmckay397
    • sineadcullinane
    • miccc
    • shanepm
    • sheyla.marhuenda
    • techfort
    • rafaeljusto
    • 1001hz
    • 4ver
    • emmetcampion
    • bakaat
    • aetheon
    • teamwork-dev
    • cianwoods
    • kersh
    • jamesdraper5
    • aodhom
    • ripexz
    • morethanaprogrammer
    • jatochnietdan
    • samternent
    • pshad0w
    • dmackey
    • yawlhead91
    • gkubisa
    • jessicaaferraz
    • arielpiecha-teamwork
    • cesartw
    • jamesmccullough
    • garymcbay
    • ekm1908
    • adamcarroll-teamwork
    • hmarron
    • bradderz
    • patrickaodh
    • vercadium
    • steve.walsh
    • victoriasloan1995
    • guillermofgorostidi
    • lucasleandro1204
    • atilkan
    • ktopouzi
    • aidancasey
    • valerio-farriciello
    • netoramalhotw
    • ap7t
    • luketynan
    • marciliotw
    • alekaei
    • twsanjay
    • chrismccormack
    • jaspiertw