DEV Community

Cover image for Real-Time WebSocket Connections for Node.js with ws-low-level
Jon Lachlan
Jon Lachlan

Posted on

Real-Time WebSocket Connections for Node.js with ws-low-level

Achieving real-time connections is easy using WebSockets. Though you may opt for long polling to update a client statelessly, the ability to handle and manage a stateful WebSocket connection makes it possible to work in real-time communications with the client.

WebSocket is a bi-directional data messaging protocol. The connection begins as an HTTP call, which initiates a handshake to work through the details of the connection. Once the connection is established, the client and server can send messages to each other. Messages are formatted as UTF-8 text or binary.

With the Node 22 update, the WebSocket client is now available in Node, so you can build server-to-server WebSocket connections with Node.js as the client.

Clearly WebSockets have a lot of value, so let's build a server!

Achieving Real-Time Connections with Node.js

In this article I'm going to show you how to get started with creating a WebSocket server for Node.js using the npm library ws-low-level. ws-low-level provides the API to receive and send messages, and handle the WebSocket handshake.

As its name suggests, ws-low-level is low-level, in the sense that it gives you access to the raw parts of the WebSocket protocol. With this access comes the trade-off of more control versus more verbosity. And ws-low-level is indeed verbose -- the example in the README file for the ws-low-level repo is over 150 lines of code!

That is not to say ws-low-level is overly complex, however. The example from the README file is simple enough.

And the ws-low-level API is actually providing you with a robust, Promise-based, standard-compliant WebSocket server. Because it is low-level, you will have the opportunity, once your server is in development, to add to it and customize it the way that you want.

Getting Started

I will walk you through setting up a WebSocket server using ws-low-level.

First, make sure you have the correct prerequisites installed. You will need Node.js, which you can get from the Node download page. This will also install npm. You can check your installation by running node --version and npm --version.

Let me explain how ws-low-level works with Node.js.

ws-low-level ties in to the standard library of Node.js. In Node.js, the WebSocket HTTP upgrade is available through Node's http package with the 'upgrade' event handler. A request to establish a WebSocket will trigger this event. Below is an example server that uses the event and logs the word "upgrade" to the console whenever a WebSocket connection is requested.

import http from 'http';

const httpServer = http.createServer(
    function (
        request /* <http.IncomingMessage> */,
        response /* <http.ServerResponse> */
    ) {
        // Handle HTTP messages by verbs like GET and POST
    }
);

httpServer.on('upgrade', function (
    request /* <http.IncomingMessage> */,
    socket /* <stream.Duplex> */,
    head /* <Buffer> websocket header */
) {
    // Handle a WebSocket connection
    console.log('upgrade');
});

httpServer.listen(3000);
Enter fullscreen mode Exit fullscreen mode

The above code shows how to use Node.js to handle a WebSocket. Note that Node.js does not handle the WebSocket handshake, nor parse incoming WebSocket frames, nor prepare outgoing messages as WebSocket frames. We need a third-party library to help get started with our WebSocket server.

Using ws-low-level

Enter ws-low-level! ws-low-level is a third-party library available on npm for handling Node.js WebSocket connections. To install the library, enter in your terminal:

npm install ws-low-level
Enter fullscreen mode Exit fullscreen mode

Now, back to our server, we can import from ws-low-level all of the imports that we will need. I recommend importing all five of the following imports, because you will eventually need them all.

import {
    sendHandshake,
    getMessagesFactory,
    sendFactory,
    prepareWebsocketFrame,
    prepareCloseFramePayload
} from 'ws-low-level';
Enter fullscreen mode Exit fullscreen mode

Now we can add a WebSocket handshake to the web server, and the connection will be established. Let's modify the callback for the 'upgrade' event to include sendHandshake.

httpServer.on('upgrade', function (
    request /* <http.IncomingMessage> */,
    socket /* <stream.Duplex> */ ,
    head /* <Buffer> websocket header */
) {
    sendHandshake(
        request,
        socket
    );
});
Enter fullscreen mode Exit fullscreen mode

The above code will complete the WebSocket handshake, establishing a WebSocket connection. (That was simple!)

Next Steps

Now that we have a connection established, it should be clear what we need to do next -- we need to handle receiving and sending messages. To continue on your journey, I recommend you proceed to the example server on ws-low-level's README. It should be clear how to use the send and receive functionalities.

This has been a brief introduction to real-time WebSocket communication for Node.js using ws-low-level. As the creator of ws-low-level, I'd like to say thank you for reading!

Top comments (0)