{"id":15812,"library":"rsocket-websocket-client","title":"RSocket WebSocket Client for Browsers","description":"rsocket-websocket-client is a JavaScript library providing a WebSocket-based RSocket client implementation primarily designed for browser environments. It is part of the broader `rsocket-js` monorepo, which aims to provide a comprehensive JavaScript implementation of the RSocket protocol. As of its current version `0.0.29-alpha.0`, it is in an active alpha development phase, indicating that it is subject to rapid changes and not yet stable for production use. RSocket is a binary protocol for application-layer communication, enabling reactive streams with models like request/response, request/stream, fire-and-forget, and channel. This client focuses specifically on the WebSocket transport, making it suitable for web applications. Its key differentiator is its adherence to the RSocket specification, offering efficient, multiplexed, and reactive communication patterns over WebSockets, in contrast to traditional REST or simpler WebSocket protocols. The release cadence is currently irregular due to its alpha status, with updates reflecting progress on the overall RSocket.js implementation.","status":"active","version":"0.0.29-alpha.0","language":"javascript","source_language":"en","source_url":"https://github.com/rsocket/rsocket-js","tags":["javascript"],"install":[{"cmd":"npm install rsocket-websocket-client","lang":"bash","label":"npm"},{"cmd":"yarn add rsocket-websocket-client","lang":"bash","label":"yarn"},{"cmd":"pnpm add rsocket-websocket-client","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Provides the core RSocket protocol implementation, interfaces, and serializers required by any RSocket client.","package":"rsocket-core","optional":false},{"reason":"Offers reactive streams primitives (Flowable, Subscriber) used for handling RSocket interactions like request-response and streams. Typically a peer dependency.","package":"rsocket-flowable","optional":false}],"imports":[{"note":"This package primarily uses ESM. CommonJS `require` may lead to issues or require specific build configurations, especially for browser consumption.","wrong":"const RSocketWebSocketClient = require('rsocket-websocket-client');","symbol":"RSocketWebSocketClient","correct":"import { RSocketWebSocketClient } from 'rsocket-websocket-client';"},{"note":"RSocketClient is a named export from `rsocket-core`, not a default export.","wrong":"import RSocketClient from 'rsocket-core';","symbol":"RSocketClient","correct":"import { RSocketClient } from 'rsocket-core';"},{"note":"Used for serialization within the RSocketClient. Correct import is a named export from `rsocket-core`.","wrong":"const { BufferEncoders } = require('rsocket-core');","symbol":"BufferEncoders","correct":"import { BufferEncoders } from 'rsocket-core';"},{"note":"The reactive streams `Flowable` class is provided by `rsocket-flowable`, not directly by `rsocket-core`.","wrong":"import { Flowable } from 'rsocket-core';","symbol":"Flowable","correct":"import { Flowable } from 'rsocket-flowable';"}],"quickstart":{"code":"import { RSocketClient, BufferEncoders, RSocketConnection, Payload } from 'rsocket-core';\nimport { RSocketWebSocketClient } from 'rsocket-websocket-client';\nimport { Flowable } from 'rsocket-flowable';\n\n// For browser environments, Buffer might not be globally available.\n// Use TextEncoder/TextDecoder for explicit Uint8Array handling, or rely on build tool polyfills.\n// This example uses Buffer.from for simplicity, which works well in Node.js or with polyfills.\n\nasync function connectAndInteract() {\n  const client = new RSocketClient({\n    serializers: BufferEncoders,\n    setup: {\n      keepAlive: 60000, // Milliseconds\n      lifetime: 180000, // Milliseconds\n      dataMimeType: 'application/json',\n      metadataMimeType: 'message/x.rsocket.routing.v0', // Or 'message/x.rsocket.composite-metadata.v0'\n    },\n    transport: new RSocketWebSocketClient({\n      url: 'ws://localhost:7000/rsocket', // Replace with your RSocket server's WebSocket URL\n      // For browser environments, explicitly provide a WebSocket constructor:\n      wsCreator: (url) => new WebSocket(url),\n    }),\n  });\n\n  let rsocket: RSocketConnection | null = null;\n  try {\n    rsocket = await client.connect();\n    console.log('RSocket client connected successfully.');\n\n    // --- Request-Response interaction ---\n    console.log('\\nSending Request-Response...');\n    const rrPayload: Payload = {\n      data: Buffer.from(JSON.stringify({ request: 'greeting' })),\n      metadata: Buffer.from('hello.world'), // Simple routing key\n    };\n    const rrResult = await Flowable.from<Payload>(rsocket.requestResponse(rrPayload)).first().toPromise();\n    console.log('Request-Response received:', rrResult.data?.toString());\n\n    // --- Request-Stream interaction ---\n    console.log('\\nSending Request-Stream...');\n    const rsPayload: Payload = {\n      data: Buffer.from(JSON.stringify({ count: 3 })),\n      metadata: Buffer.from('stream.data'), // Simple routing key\n    };\n    rsocket.requestStream(rsPayload).subscribe({\n      onComplete: () => console.log('Request-Stream completed.'),\n      onError: (error) => console.error('Request-Stream error:', error),\n      onNext: (payload) => console.log('Request-Stream data:', payload.data?.toString()),\n      onSubscribe: (subscription) => subscription.request(Infinity), // Request all available items\n    });\n\n    // Keep the connection open for a few seconds to receive stream data\n    await new Promise(resolve => setTimeout(resolve, 5000));\n\n  } catch (error) {\n    console.error('Failed to connect or interact with RSocket server:', error);\n  } finally {\n    if (rsocket) {\n      client.close();\n      console.log('RSocket client disconnected.');\n    }\n  }\n}\n\nconnectAndInteract();","lang":"typescript","description":"Demonstrates connecting an RSocket client via WebSocket, performing a Request-Response interaction, and subscribing to a Request-Stream, including proper connection setup and teardown for a browser environment."},"warnings":[{"fix":"Monitor the `rsocket-js` monorepo's releases and changelogs for updates. Pin exact versions in `package.json` to prevent unexpected breaking changes.","message":"This package is currently in an alpha development phase (v0.0.29-alpha.0). The API is subject to frequent, significant, and breaking changes without prior notice. It is not recommended for production environments where API stability is critical.","severity":"breaking","affected_versions":">=0.0.0-alpha.0"},{"fix":"Ensure your build setup includes a `Buffer` polyfill (e.g., in Webpack 5 config) or explicitly convert your payload data to `Uint8Array` before passing it to RSocket methods and convert `Uint8Array` responses back to string/object.","message":"In browser environments, the `Buffer` global is not natively available. While `rsocket-js` often uses `Buffer` internally, payload data handling might require polyfills or explicit usage of `Uint8Array` with `TextEncoder`/`TextDecoder` for maximum compatibility.","severity":"gotcha","affected_versions":">=0.0.0-alpha.0"},{"fix":"Carefully configure `dataMimeType` and `metadataMimeType` in the `RSocketClient` setup options to match the server's expectations. Common values include 'application/json', 'text/plain', 'message/x.rsocket.routing.v0', or 'message/x.rsocket.composite-metadata.v0'.","message":"Mismatched `dataMimeType` or `metadataMimeType` between client and server can lead to communication failures or malformed payloads, as RSocket relies on these for proper serialization/deserialization.","severity":"gotcha","affected_versions":">=0.0.0-alpha.0"},{"fix":"When initializing `RSocketWebSocketClient`, pass an object `{ url: 'ws://your-server', wsCreator: (url) => new WebSocket(url) }` to ensure the client can instantiate the browser's native WebSocket.","message":"The `RSocketWebSocketClient` requires a `wsCreator` function when used in a browser environment to provide the correct `WebSocket` constructor, as Node.js's global `WebSocket` is not available.","severity":"gotcha","affected_versions":">=0.0.0-alpha.0"},{"fix":"Always call `.subscribe()` on `Flowable` instances for stream interactions, or use `.first().toPromise()` (if expecting a single result) for request-response patterns, ensuring you handle `onNext`, `onError`, and `onComplete` callbacks.","message":"RSocket interactions like `requestResponse` and `requestStream` return `Flowable` instances from `rsocket-flowable`. Incorrectly handling these reactive streams (e.g., forgetting to `subscribe` or `toPromise()`) will result in no data being exchanged.","severity":"gotcha","affected_versions":">=0.0.0-alpha.0"}],"env_vars":null,"last_verified":"2026-04-21T00:00:00.000Z","next_check":"2026-07-20T00:00:00.000Z","problems":[{"fix":"If using Webpack 5, add `resolve: { fallback: { 'buffer': require.resolve('buffer/') } }` to your `webpack.config.js`. Alternatively, explicitly use `new TextEncoder().encode(JSON.stringify(data))` for outgoing data and `new TextDecoder().decode(payload.data)` for incoming `Uint8Array`.","cause":"Attempting to use `Buffer.from` or other `Buffer` methods in a browser environment without a polyfill.","error":"TypeError: Buffer is not defined"},{"fix":"Verify the RSocket server is running and accessible at the specified URL (`ws://localhost:7000/rsocket`). Check server logs for handshake errors and ensure `dataMimeType` and `metadataMimeType` are correctly configured on both client and server.","cause":"Generic RSocket connection failure, often due to server not running, incorrect URL, firewall, or protocol mismatch during handshake.","error":"Failed to connect or interact with RSocket server: Error: RSocket: Connection error."},{"fix":"Ensure `client` is instantiated with `const client = new RSocketClient({...});` and `RSocketClient` is correctly imported as a named export from `rsocket-core`.","cause":"The `client` variable was not properly initialized as an instance of `RSocketClient` or was imported incorrectly.","error":"TypeError: client.connect is not a function"},{"fix":"Ensure `import { Flowable } from 'rsocket-flowable';` is present and wrap the `requestResponse` call: `await Flowable.from(rsocket.requestResponse(payload)).first().toPromise();`","cause":"`toPromise()` is a method of `Flowable` (from `rsocket-flowable`), and `requestResponse` returns a `Flowable` which might need explicit conversion or `rsocket-flowable` might not be imported.","error":"TypeError: rsocket.requestResponse(...).toPromise is not a function"}],"ecosystem":"npm"}