WebSocket clients
This feature is available only for the Enterprise plan. To get started, reach out to support@buildwithfern.com.
Fern generates typed WebSocket clients from your AsyncAPI channel definitions. The generated clients handle connection management, typed send/receive messages, and automatic reconnection.
Fern generates WebSocket clients for TypeScript, Python, Java, C#, Rust, Go, Ruby, PHP, and Swift.
Enable WebSocket client generation
Set generation.webSockets: true in sdk-config.yml. Set it in the top-level generation block to enable WebSocket clients for every target, or in a target’s generation block for one language. A target’s value overrides the top-level value:
Java generates WebSocket clients by default with no additional configuration; set webSockets: false to turn them off. Every other language generates them only when webSockets is true. With WebSocket generation off, the SDK still includes the message types.
Generated SDK behavior
Given an AsyncAPI channel definition like:
Fern generates the following client code.
Send methods are named send + the message name from the spec. The SensorReading message produces sendSensorReading in TypeScript, Java, Go, PHP, and Swift, and send_sensor_reading in Python, Ruby, and Rust. C# uses overloaded Send() methods instead.
Receive handling varies by language:
- TypeScript — a generic
socket.on("message", handler)callback - Python — typed responses from
ws.recv() - Java — per-message-type handlers like
onPlantStatus(handler) - C# — typed
Event<T>properties likePlantStatus.Subscribe(handler) - Rust — a typed enum from
ws.recv() - Go — per-message-type handlers like
OnPlantStatus(handler), thenStart() - Ruby —
recv,each, oron(...)handlers withstart_listening - PHP — iterate the socket with
foreach, or callreceive() - Swift —
for await event in socket.events, with.message(.plantStatus(...))
TypeScript
Python
Java
C#
Rust
The TypeScript SDK generates a typed socket class with send methods, event handlers, and a ReconnectingWebSocket that automatically retries dropped connections.
Detach a handler with socket.off(event, handler). By default, registering a second handler for the same event replaces the first; set websocketHandlerMode: accumulate in generators.yml to fire every registered handler in order.
The connection call accepts reconnectAttempts (default 30, 0 disables reconnection) and a shouldReconnect predicate that receives the CloseEvent when the server closes the connection and decides whether to reconnect. The default reconnects on every server close code except 1000. Return false to treat a server close as terminal, for example after the client has sent an end-of-stream message:
shouldReconnect applies only to server-initiated closes. Connection errors and connection timeouts still fire close handlers but always retry up to reconnectAttempts, regardless of the predicate. shouldReconnect also isn’t consulted after socket.close() or when the abortSignal aborts, and a predicate that throws is treated as terminal. Calling socket.connect() after retries are exhausted starts a new connection attempt.
Authentication
In TypeScript, Python, Java, and Rust, WebSocket clients automatically inherit the authentication configured on the root client. Headers — including bearer tokens, API keys, and custom headers — are sent with the WebSocket handshake request. In TypeScript, the handshake carries the root client’s credentials when the auth scheme is declared under api.auth in sdk-config.yml.
In C#, the WebSocket client created by the root client’s factory method sends the root client’s credentials and ClientOptions.AdditionalHeaders on the handshake and on every reconnect. Per connection, Options.AdditionalHeaders replaces a header of the same name, and a null value removes it.
Defining WebSocket channels
WebSocket clients are generated from channel definitions in your AsyncAPI specification. For defining channels, messages, and operations, see Publish/subscribe operations.