The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

WebSocket - WebSocket Javascript Class

SYNOPSIS

    var ws = new Perl.WebSocket( "wss://chat.example.org/v2",
    {
        max: 7, // max reconnect attempts
        onerror: function(event)
        {
            console.log( "WebSocket error observed:" + event );
        },
        onmaximum: function(event)
        {
            console.log( "Reached maximum retry to connect to the WebSocket server." );
        },
        onmessage: function(event)
        {
            console.log( "WebSocket message received:" + event );
        },
        onopen: function(event)
        {
            console.log( "WebSocket is open now." );
        },
        onreconnect: function()
        {
            console.log( "Attempting to reconnect to WebSocket server." );
        },
        protocol: ['some', 'stuff'],
        timeout: 5000 // 5 seconds
    });
    ws.send( "some raw data" );
    # Will be encapsulated into json before being sent
    ws.json( "some message" );

VERSION

    v0.1.0

DESCRIPTION

This Javascript class serves to make WebSocket connections. It uses the security principle of double authentication tokens as described here.

Upon connection, an authentication token (previously set and provided by a remote server and stored in the local storage) will be passed as a cookie to the remote websocket server, as a query string to the connection url with the parameter csrf

METHODS

new

Instantiate a new WebSocket object provided with the following options:

max

Integer. Maximum number of reconnect attempts. Defaults to infinity.

onclose
    ws.onclose = function(event)
    {
        console.log( "WebSocket is closed now." );
    };

Optional function callback triggered when the server connection is closed. It "is called when the WebSocket connection's readyState changes to CLOSED"

The callback function is called with a CloseEvent object.

The CloseEvent object "inherits properties from its parent, Event" and has the following properties, according to Mozilla:

CloseEvent.code

Read only. Returns an unsigned short containing the close code sent by the server.

CloseEvent.reason

Read only. Returns a DOMString indicating the reason the server closed the connection. This is specific to the particular server and sub-protocol.

CloseEvent.wasClean

Read only. Returns a boolean value that Indicates whether or not the connection was cleanly closed.

See for more information: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/onclose

onerror
    ws.onerror = function(event)
    {
        console.log( "WebSocket error observed:" + event );
    };

Optional function callback triggered "whenever an error event occurs on the WebSocket connection."

The callback function is called with the event object.

See for more information: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/onerror

onmaximum
    ws.onmaximum = function(event)
    {
        console.log( "Reached maximum retry to connect to the WebSocket server." );
    }

Optional function callback triggered upon reconnect when the maximum attempts have been reached. This is not part of the WebScket api.

The callback function is called with the event object.

onmessage
    ws.onmessage = function(json, event)
    {
        console.log( "WebSocket message received: " + JSON.stringify(json, null, 4) );
    };

Optional function callback triggered when a message is received from the server. "It is called with a MessageEvent."

The message from the server is expected to be a valid json data, which will be parsed and passed to the callback function.

A second parameter is passed, which is a MessageEvent object.

The MessageEvent object "inherits properties from its parent, Event" and has the following properties, according to Mozilla:

MessageEvent.data

Read only. The data sent by the message emitter.

MessageEvent.origin

Read only. A USVString representing the origin of the message emitter.

MessageEvent.lastEventId

Read only. A DOMString representing a unique ID for the event.

MessageEvent.source

Read only. A MessageEventSource (which can be a WindowProxy, MessagePort, or ServiceWorker object) representing the message emitter.

MessageEvent.ports

Read only. An array of MessagePort objects representing the ports associated with the channel the message is being sent through (where appropriate, e.g. in channel messaging or when sending a message to a shared worker).

See for more information: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/onmessage

onopen
    ws.onopen = function(event)
    {
        console.log( "WebSocket is open now." );
    };

Optional function callback triggered when the server connection is opened. It "is called when the WebSocket connection's readyState changes to 1; this indicates that the connection is ready to send and receive data."

The callback function is called with the event object.

See for more information: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/onopen

onreconnect
    ws.onreconnect = function()
    {
        console.log( "Attempting to reconnect to WebSocket server." );
    }

Optional function callback triggered when trying to reconnect to the server, and before an connection attemept is made. This is not part of the WebScket api.

The callback function is called with the event object.

protocols
    var protocol = ws.protocol;

Optional array of protocols. Default to empty array.

"The WebSocket.protocol read-only property returns the name of the sub-protocol the server selected; this will be one of the strings specified in the protocols parameter when creating the WebSocket object, or the empty string if no connection is established."

See for more information: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/protocol

timeout

Optional integer value for timeout to reconnect.

addEventListener( type, function )

Adds an event listener provided with function for the given type

close(code, reason)

    ws.close();

    ws.close(code);

    ws.close(reason);

    ws.close(code, reason);

Closes the connection.

Takes 2 parameters:

code

Optional. A numeric value indicating the status code explaining why the connection is being closed. If this parameter is not specified, a default value of 1005 is assumed. See the list of status codes of CloseEvent for permitted values.

Known codes are:

1000

The default, normal closure (used if no code supplied),

"1000 indicates a normal closure, meaning that the purpose for which the connection was established has been fulfilled."

1001

The party is going away, e.g. server is shutting down, or a browser leaves the page.

"1001 indicates that an endpoint is "going away", such as a server going down or a browser having navigated away from a page."

1002

"1002 indicates that an endpoint is terminating the connection due to a protocol error."

1003

"1003 indicates that an endpoint is terminating the connection because it has received a type of data it cannot accept (e.g., an endpoint that understands only text data MAY send this if it receives a binary message)."

1004

Reserved for future use.

1005

"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."

1006

No way to set such code manually, indicates that the connection was lost (no close frame).

"1006 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 the connection was closed abnormally, e.g., without sending or receiving a Close control frame."

1007

"1007 indicates that an endpoint is terminating the connection because it has received data within a message that was not consistent with the type of the message (e.g., non-UTF-8 [RFC3629] data within a text message)."

1008

"1008 indicates that an endpoint is terminating the connection because it has received a message that violates its policy. This is a generic status code that can be returned when there is no other more suitable status code (e.g., 1003 or 1009) or if there is a need to hide specific details about the policy."

1009

The message is too big to process.

"1009 indicates that an endpoint is terminating the connection because it has received a message that is too big for it to process."

1010

"1010 indicates that an endpoint (client) is terminating the connection because it has expected the server to negotiate one or more extension, but the server didn't return them in the response message of the WebSocket handshake. The list of extensions that are needed SHOULD appear in the /reason/ part of the Close frame. Note that this status code is not used by the server, because it can fail the WebSocket handshake instead."

1011

Unexpected error on server.

"1011 indicates that a server is terminating the connection because it encountered an unexpected condition that prevented it from fulfilling the request."

1015

"1015 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 the connection was closed due to a failure to perform a TLS handshake (e.g., the server certificate can't be verified)."

Full list of codes can be found at RFC6455, §7.4.1.

See rfc6455 documentation for more information.

reason

Optional. A human-readable string explaining why the connection is closing. This string must be no longer than 123 bytes of UTF-8 text (not characters).

See rfc6455 documentation for more information.

See for more information: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close

getCsrf()

Takes no arguments and returns the current csrf token stored in local storage, if any, otherwise returns undefined

isClosed()

Returns true if the connection to the WebSocket server is closed, false otherwise.

isClosing()

Returns true if the connection to the WebSocket server is shutting down, false otherwise.

isConnecting()

Returns true if there is an ongoing connection attempt to the WebSocket server, false otherwise.

isConnected()

Returns true if connected to the WebSocket server, false otherwise.

json(data)

Provided with some json data, and this will add the current csrf token to json property csrf and send the stringified json data to the WebSocket server.

makePropertyReadOnly(property)

Provided with a WebSocket property and this will alias it to our AI WebSocket object, but make it read-only.

makePropertyReadWrite(property)

Provided with a WebSocket property and this will alias it to our AI WebSocket object, and make it read-writable.

noop()

A default function that does absolutely nothing and is used when no function is provided.

open()

Initiiate a connection to the remove WebSocket server at the "uri" specified during object instantiation.

It will retrieve the current csrf token from the local storage, if any, and add it as a query string to the connection url.

If it cannot connect, it will throw an error.

reconnect()

Attempts to reconnect until max parameter is reached.

Upon every attempt, it will call the callback function set with onreconnect

If max attempts have been reached, it will call the callback function set with onmaximum

send(data)

    ws.send( "Hello server!" );

Enqueues data to be transmitted.

"The WebSocket.send() method enqueues the specified data to be transmitted to the server over the WebSocket connection, increasing the value of bufferedAmount by the number of bytes needed to contain the data. If the data can't be sent (for example, because it needs to be buffered but the buffer is full), the socket is closed automatically."

The data may be one of the following data types:

USVString

A text string. The string is added to the buffer in UTF-8 format, and the value of bufferedAmount is increased by the number of bytes required to represent the UTF-8 string.

See for more information: https://developer.mozilla.org/en-US/docs/Web/API/USVString

ArrayBuffer

You can send the underlying binary data used by a typed array object; its binary data contents are queued in the buffer, increasing the value of bufferedAmount by the requisite number of bytes.

See for more information: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer

Blob

Specifying a Blob enqueues the blob's raw data to be transmitted in a binary frame. The value of bufferedAmount is increased by the byte size of that raw data.

See for more information: https://developer.mozilla.org/en-US/docs/Web/API/Blob

ArrayBufferView

You can send any JavaScript typed array object as a binary frame; its binary data contents are queued in the buffer, increasing the value of bufferedAmount by the requisite number of bytes.

See for more information: https://developer.mozilla.org/en-US/docs/Web/API/ArrayBufferView

See for more information: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send

socket

Returns the actual WebSocket object.

PROPERTIES

binaryType

    // Create WebSocket connection.
    const socket = new Perl.WebSocket( "ws://localhost:8080" );
    // Change binary type from "blob" to "arraybuffer"
    socket.binaryType = "arraybuffer";

    // Listen for messages
    socket.addEventListener("message", function (event) {
        if(event.data instanceof ArrayBuffer) {
            // binary frame
            const view = new DataView(event.data);
            console.log(view.getInt32(0));
        } else {
            // text frame
            console.log(event.data);
        }
    });

"The binary data type used by the connection."

Possible values:

blob

Use Blob objects for binary data. This is the default value.

arraybuffer

Use ArrayBuffer objects for binary data.

See for more information: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/binaryType

bufferedAmount

    var bufferedAmount = ws.bufferedAmount;

Read only. An unsigned long.

"The number of bytes of queued data."

"The WebSocket.bufferedAmount read-only property returns the number of bytes of data that have been queued using calls to send() but not yet transmitted to the network. This value resets to zero once all queued data has been sent. This value does not reset to zero when the connection is closed; if you keep calling send(), this will continue to climb."

See for more information: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/bufferedAmount

extensions

    var extensions = ws.extensions;

Read only. "The extensions selected by the server."

"The WebSocket.extensions read-only property returns the extensions selected by the server. This is currently only the empty string or a list of extensions as negotiated by the connection."

See for more information: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/extensions

protocol

    var protocol = ws.protocol;

Read only. "The sub-protocol selected by the server."

"The WebSocket.protocol read-only property returns the name of the sub-protocol the server selected; this will be one of the strings specified in the protocols parameter when creating the WebSocket object, or the empty string if no connection is established."

See for more information: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/protocol

readyState

Read only. "The current state of the connection."

"The WebSocket.readyState read-only property returns the current state of the WebSocket connection."

Value State Description
0 CONNECTING Socket has been created. The connection is not yet open.
1 OPEN The connection is open and ready to communicate.
2 CLOSING The connection is in the process of closing.
3 CLOSED The connection is closed or couldn't be opened.

See for more information: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState

url

    var url = ws.url;

Read only. "The absolute URL of the WebSocket."

"The WebSocket.url read-only property returns the absolute URL of the WebSocket as resolved by the constructor."

See for more information: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/url and https://datatracker.ietf.org/doc/html/rfc6455#page-14

CONSTANTS

CONNECTING

0

OPEN

1

CLOSING

2

CLOSED

3

SEE ALSO

Mozila documentation, JavaScript Info documentation, rfc6455, https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications, https://javascript.info/websocket

AUTHOR

Jacques Deguest <jack@deguest.jp>

COPYRIGHT & LICENSE

Copyright(c) 2021 DEGUEST Pte. Ltd. DEGUEST Pte. Ltd.

You can use, copy, modify and redistribute this package and associated files under the same terms as Perl itself.

12 POD Errors

The following errors were encountered while parsing the POD:

Around line 231:

Expected text after =item, not a number

Around line 237:

Expected text after =item, not a number

Around line 241:

Expected text after =item, not a number

Around line 245:

Expected text after =item, not a number

Around line 249:

Expected text after =item, not a number

Around line 253:

Expected text after =item, not a number

Around line 259:

Expected text after =item, not a number

Around line 263:

Expected text after =item, not a number

Around line 267:

Expected text after =item, not a number

Around line 273:

Expected text after =item, not a number

Around line 277:

Expected text after =item, not a number

Around line 283:

Expected text after =item, not a number