javascripttypescriptwebsocketping

Overriding the default ping protocol for native Javascript websockets


I am attempting to create a protocol for handling stale websocket connections for my Expo (React Native) project on both the client and server side. Since the 'ws' package has built-in callback handling for the 'pong' event (and for sending a ping), management on the server (NodeJS) is easy enough.

Where I am having trouble is with the client, as the native WebSocket object does not present a callback for its response to pings from the server. It does respond to pings from the server with the correct opcode (0x9), but such messages are never passed to the WebSocket.onmessage handler.

This is my attempt at a client-side ping handler:

const heartbeat = () => {
            console.log("heartbeat");

            clearTimeout(pingTimeout!);

            pingTimeout = setTimeout(() => {
                socket.close();
                setResetConnection(rc => !rc);
            }, HEARTBEAT_INTERVAL + HEARTBEAT_LATENCY);
};

socket.onmessage = (event) => {
            console.log("message");

            if (event.data instanceof Blob) {
                console.log("received ping");
                heartbeat();
                const response = new ArrayBuffer(1);
                const view = new Uint8Array(response);
                view[0] = 0x9;
                socket.send(view);
                return;
            }

            [...remaining onmessage code...]
}

With socket initialized as var socket = new WebSocket("ws://ipaddr:8080");

As mentioned, the pong is sent to the server accordingly without allowing the client any space for additional logic. I would like to find a way to override this behavior without constructing my own ping/pong protocol.


Solution

  • @dandavis is correct; using socket.onclose() is perfectly acceptable