WebSockets
Added in: v4.2.0
Harper supports WebSocket connections through the REST interface, enabling real-time bidirectional communication with resources. WebSocket connections target a resource URL path — by default, connecting to a resource subscribes to changes for that resource.
Configuration
WebSocket support is enabled automatically when the rest plugin is enabled. To disable it:
rest:
webSocket: false
Connecting
A WebSocket connection to a resource URL subscribes to that resource and streams change events:
let ws = new WebSocket('wss://server/my-resource/341');
ws.onmessage = (event) => {
let data = JSON.parse(event.data);
};
By default, new WebSocket('wss://server/my-resource/341') accesses the resource defined for my-resource with record id 341 and subscribes to it. When the record changes or a message is published to it, the WebSocket connection receives the update.
Custom connect() Handler
WebSocket behavior is driven by the connect(incomingMessages) method on a resource class. The method must return an async iterable (or generator) that produces messages to send to the client. For more on implementing custom resources, see Resource API.
Simple echo server:
export class Echo extends Resource {
async *connect(incomingMessages) {
for await (let message of incomingMessages) {
yield message; // echo each message back
}
}
}
Using the default connect with event-style access:
The default connect() returns a convenient streaming iterable with:
- A
send(message)method for pushing outgoing messages - A
closeevent for cleanup on disconnect
export class Example extends Resource {
connect(incomingMessages) {
let outgoingMessages = super.connect();
let timer = setInterval(() => {
outgoingMessages.send({ greeting: 'hi again!' });
}, 1000);
incomingMessages.on('data', (message) => {
outgoingMessages.send(message); // echo incoming messages
});
outgoingMessages.on('close', () => {
clearInterval(timer);
});
return outgoingMessages;
}
}
MQTT over WebSockets
Harper also supports MQTT over WebSockets. The sub-protocol must be set to mqtt as required by the MQTT specification:
Sec-WebSocket-Protocol: mqtt
See MQTT Overview for full MQTT documentation.
Message Ordering in Distributed Environments
Harper prioritizes low-latency delivery in distributed (multi-node) environments. Messages are delivered to local subscribers immediately upon arrival — Harper does not delay messages for inter-node coordination.
In a scenario where messages arrive out-of-order across nodes:
- Non-retained messages (published without a
retainflag): Every message is delivered to subscribers in the order received, even if out-of-order relative to other nodes. Good for use cases like chat where every message must be delivered. - Retained messages (published with
retain, or PUT/updated in the database): Only the message with the latest timestamp is kept as the "winning" record. Out-of-order older messages are not re-delivered. This ensures eventual consistency of the most recent record state across the cluster. Good for use cases like sensor readings where only the latest value matters.
See Also
- Server-Sent Events — One-way real-time streaming
- MQTT Overview — Full MQTT pub/sub documentation
- REST Overview — HTTP methods and URL structure
- Resources — Custom resource API including
connect()