jellysocket

1.0.8 • Public • Published

jellysocket Build Status

JellySocket is a thin abstraction of a pure WebSocket, providing a streamlined API and reliable error handling. You are expected to extend the JellySocket class to create your own custom protocols. The hard stuff is all taken care of for you. All you have to worry about is the data layer.

JellySocket weighs in at only 2,251 bytes minified and gzipped.

Installation

npm install --save jellysocket

Usage

var JellySocket = require('jellysocket');
 
function SuperSocket(uri) {
    JellySocket.call(this, uri);
    
    this.on('_message', function (ui8Array) {
        this.emit('message', ui8Array);
    });
}
SuperSocket.prototype.__proto.__ = JellySocket.prototype;
SuperSocket.prototype.protocol = 'super-cool-protocol-1.0';
 
SuperSocket.prototype.send = function (ui8Array) {
    return this._send(ui8Array);
};
An example client:
var supersocket = new SuperSocket('ws://myapp.com/path/to/app');
supersocket.on('message', function (data) {
    supersocket.send(data);
});
An example server:
var Application = require('jellysocket').Application;
var app = Application(server, SuperSocket);
 
app.on('connection', function (supersocket) {
    supersocket.send(getUint8Array());
});

The idea is that your subclass hooks into the _message event and the _send method, while exposing more useful events and methods as public API.

When you extend the JellySocket class, you must add a string protocol property to the prototype. This is how your protocol will be identified within the WebSockets subprotocol scheme.

MyCustomSocket.prototype.protocol = 'super-cool-protocol-1.0'

Browser support

Much of jellysocket's awesomeness comes from her apt use of modern web technologies. She requires WebSocket with binary support (no legacy versions, only RFC-6455).

Natively, this package is supported by:

  • Chrome 16+
  • Firefox 11+
  • Safari 7+
  • Opera 12.1+
  • Internet Exporer 10+
  • Edge

API

class JellySocket

On the client, these instances can be created by invoking the constructor.

On the server, these instances are exposed by JellySocketApplication in the connection event.

For non-browser clients, you can pass an optional options object as a second argument, which will get passed to the underlying ws module.

.disconnect([error]) -> this

Closes the connection. The disconnect event is immediately emitted. You can optionally pass an Error object, which will be exposed in the disconnect event at both endpoints.

._send(data) -> this

Sends the given data to the other endpoint. Use this method as the underlying transport mechanism for building your own API. This method is not intended to be used by the consumer of your API.

The data argument must be a Uint8Array. Since the Node.js Buffer object inherits from Uint8Array, you can send those too.

get .connected -> boolean

Indicates if the connection is open and events may be sent back and forth.

get .bufferedAmount -> number

Returns the number of bytes in the internal buffer. In advanced applications, this can be monitered to adjust network usage rates.

JellySocket Events

JellySocket exposes three events:

  • connect
  • disconnect
  • _message

The connect event is triggered on a client when an open connection has been established and data may be sent back and forth.

The disconnect event is triggered when the connection has been closed. If it was closed because of an error, the first argument of this event is the associated Error object (otherwise null).

The _message event is triggered when the JellySocket receives data. The first argument of this event will be a Uint8Array of that data. In Node.js, you will get a Buffer object instead (which inherits from Uint8Array). This event is intended to be used by your subclass, but not by the users of that subclass.

class JellySocketApplication

On the server only:

var JellySocketApplication = require('jellysocket').Application
var app = new JellySocketApplication(server, MyCustomSocketClass, options)

The server argument must be a http.Server or https.Server object. MyCustomSocketClass must be a subclass of JellySocket.

Options

options.path

The path of the WebSocket server.

Default: "/"

options.verifyClient

You may supply a verifyClient function which must return true for each client wishing to connect to the WebSocket endpoint. The function may have the following two signatures:

function verifyClient(info) { // synchronous
    return false
}
function verifyClient(info, cb) { // asynchronous
    cb(false, 401, 'Unauthorized')
}

info is an object with the following properties:

  • string info.origin
  • boolean info.secure
  • http.IncomingMessage info.req

options.heartbeat

If this option is set, all clients of an JellySocketApplication will periodically be sent a heartbeat. If a client endpoint does not respond after too many heartbeats, the connection will be forcefully destroyed. You can set options.heartbeat to an integer to dictate how frequenty (in seconds) heartbeats are sent. A value of 0 or Infinity will cause this instance of JellySocketApplication to not send and track heartbeats.

Default: 0

options.heartbeatForgiveness

This is the maximum number of heatbeats a client can miss before the connection is forcefully destroyed. A value of 0 or Infinity means clients will never be disconnected as a result of being unresponsive. As an example, if this option is 5, and options.heartbeat is 30, then clients would get disconnected after 150 seconds of unresponsiveness.

Default: 0

.lock() -> this

Prevents new clients from connecting to the websocket endpoint.

.unlock() -> this

Allows new clients to connect to the websocket endpoint. When an JellySocketApplication instance is created, it starts out unlocked.

.disconnect([error]) -> this

Locks the JellySocketApplication, and invokes the .disconnect() method on each connected client.

get .clients -> Set (read-only)

Returns a read-only Set of the clients that are connected to the JellySocketApplication. The returned Set is live, meaning its contents will change constantly as clients connect and disconnect. To get a static snapshot of the connected clients, use var clients = new Set(app.clients).

get .server -> http.Server

Returns the http(s) server that is associated with this JellySocketApplication.

get .isLocked -> boolean

Returns whether the JellySocketApplication is currently rejecting new clients.

JellySocketApplication Events

JellySocketApplication exposes two events:

  • connection
  • vacant

The connection event is triggered when a client successfully connects to the WebSocket server. The first argument of this event will an instance of JellySocket (more specifically, an instance of your subclass of JellySocket).

The vacant event is triggered when the JellySocketApplication is locked, and no clients are connected.

Notes

By default, when a client tries to connect to your WebSocket server at an unused path, their connection will hang forever. This allows other WebSocket modules to share the same HTTP server by handling different paths. However, if a path is not used by any module, preferably that connection will be ended with a 404 Not Found response. JellySocket provides a convenient way of doing this.

var JellySocket = require('jellysocket');
server.on('upgrade', JellySocket.Application.upgradeNotFound);

Make sure that JellySocket.Application.upgradeNotFound is the LAST upgrade event added to the server.

License

MIT

Package Sidebar

Install

npm i jellysocket

Weekly Downloads

1

Version

1.0.8

License

MIT

Last publish

Collaborators

  • joshuawise