RSocket WebSocket Server
rsocket-websocket-server provides a robust implementation of an RSocket server that operates over the WebSocket protocol, enabling reactive, multiplexed, and message-driven communication between applications. As part of the rsocket-js monorepo, it integrates seamlessly with other RSocket.js components like rsocket-core for protocol handling and various adapters. Currently, the package is in an alpha state, with 0.0.29-alpha.0 being its latest version, indicating ongoing development and pre-production readiness. The release cadence is tied to the broader rsocket-js monorepo development, which saw a significant TypeScript migration in 1.0.0-alpha.1 across its packages. Its key differentiator is offering a full RSocket server implementation specifically for WebSocket connections, adhering to the RSocket specification for high-performance, resilient, and responsive microservices and real-time applications.
Common errors
-
Error: Expected Metadata flag to be present for metadata. FrameType: PAYLOAD
cause A client is sending a payload with metadata but the Metadata flag in the frame header is missing, possibly due to an older or misconfigured client library not compatible with the server's strict interpretation after `v0.0.29-alpha.0`.fixUpdate the RSocket client library to a version compatible with `rsocket-websocket-server@0.0.29-alpha.0` or later. Verify the client's payload builder correctly sets the Metadata flag when metadata is provided. -
Error: listen EADDRINUSE :::8080
cause The specified port for the `RSocketWebSocketServer` (e.g., 8080) is already in use by another process on the system, preventing the RSocket server from binding to it.fixChange the port number in your server configuration (e.g., to `8081`) or terminate the process currently occupying the port using a tool like `lsof -i :8080` (macOS/Linux) or `netstat -ano | findstr :8080` (Windows). -
TypeError: RSocketWebSocketServer is not a constructor
cause This typically happens when mixing CommonJS `require()` with an ESM-only or ESM-first library, or when using incorrect named/default imports. The `rsocket-js` monorepo targets modern JavaScript environments including ESM.fixEnsure you are using ES module imports: `import { RSocketWebSocketServer } from 'rsocket-websocket-server';` instead of `const RSocketWebSocketServer = require('rsocket-websocket-server');`. If in Node.js, ensure your `package.json` has `"type": "module"` or your file uses the `.mjs` extension for ESM imports.
Warnings
- breaking The `rsocket-js` monorepo, including `rsocket-websocket-server`, is currently in an alpha state (`0.0.29-alpha.0` for this package, broader `1.0.0-alpha.x` for the monorepo). This means APIs are subject to change without adhering to semantic versioning, and stability cannot be guaranteed for production environments. Users should anticipate frequent breaking changes.
- breaking In `v0.0.29-alpha.0`, a fix was introduced to correctly add the Metadata flag when sending stream payloads with metadata. This change might require client-side adjustments if clients were previously tolerant of or exploiting the incorrect flag state, potentially leading to misinterpretation of frames or connection issues.
- gotcha Since the `1.0.0-alpha.1` release (for the monorepo), a significant TypeScript migration occurred across `rsocket-js` packages. While `rsocket-websocket-server` itself might not have had direct API changes from this, interacting with other `rsocket-js` packages or custom `Responder` implementations might require strict adherence to TypeScript types, potentially revealing type errors that were previously overlooked in JavaScript.
- gotcha The `v0.0.29-alpha.0` release added support for throwing errors with custom error codes. While a new feature, ensure your `Responder` implementations correctly handle and potentially throw `RSocketError` instances with appropriate codes, and that clients are prepared to receive and interpret these custom error codes for richer error feedback.
Install
-
npm install rsocket-websocket-server -
yarn add rsocket-websocket-server -
pnpm add rsocket-websocket-server
Imports
- RSocketWebSocketServer
const RSocketWebSocketServer = require('rsocket-websocket-server');import { RSocketWebSocketServer } from 'rsocket-websocket-server'; - RSocketServer
import RSocketServer from 'rsocket-core';
import { RSocketServer, Payload, Responder } from 'rsocket-core'; - Single, Flowable
import { Observable, Subject } from 'rxjs';import { Single, Flowable } from 'rsocket-flowable';
Quickstart
import { RSocketServer, Payload, Responder } from 'rsocket-core';
import { RSocketWebSocketServer } from 'rsocket-websocket-server';
import { Flowable, Single } from 'rsocket-flowable';
const port = process.env.PORT ?? 8080;
class MyResponder implements Responder {
fireAndForget(payload: Payload): void {
console.log(`Received fire and forget: ${payload.data?.toString()}`);
}
requestResponse(payload: Payload): Single<Payload> {
console.log(`Received request-response: ${payload.data?.toString()}`);
return Single.of({
data: Buffer.from(`Response to ${payload.data?.toString()}`),
metadata: payload.metadata,
});
}
requestStream(payload: Payload): Flowable<Payload> {
console.log(`Received request-stream: ${payload.data?.toString()}`);
return Flowable.just(
{ data: Buffer.from('Stream Item 1') },
{ data: Buffer.from('Stream Item 2') },
{ data: Buffer.from('Stream Item 3') }
).delayElements(500); // Simulate some delay
}
requestChannel(payloads: Flowable<Payload>): Flowable<Payload> {
console.log(`Received request-channel setup payload:`);
return payloads.map(p => {
console.log(`Channel data: ${p.data?.toString()}`);
return {
data: Buffer.from(`Echo: ${p.data?.toString()}`),
metadata: p.metadata,
};
});
}
}
const server = new RSocketServer({
transport: new RSocketWebSocketServer({ port }),
responder: new MyResponder(),
});
server.start().then(() => {
console.log(`RSocket WebSocket Server started on port ${port}`);
console.log('Use Ctrl+C to stop');
}).catch(error => {
console.error('Server failed to start:', error);
});
process.on('SIGINT', () => {
server.shutdown().then(() => {
console.log('Server gracefully shut down.');
process.exit(0);
}).catch(error => {
console.error('Error during server shutdown:', error);
process.exit(1);
});
});