Expand description
A client for Rails’ Action Cable.
A Client owns one WebSocket connection to an Action Cable server and multiplexes any
number of channel subscriptions over it. It keeps the connection alive the way the
official JavaScript client does: the server beats a ping every three seconds, and a
connection that goes quiet for longer than ClientBuilder::stale_after is torn down
and redialed with backoff. Subscriptions survive reconnects; they are resubscribed as
soon as the server says welcome.
use actioncable::{Client, Identifier};
use serde_json::json;
let client = Client::builder("wss://example.com/cable").build()?;
client.connect().await?;
let room = client
.subscribe(Identifier::new("RoomChannel").param("id", 42))
.await?;
let reader = room.clone();
tokio::spawn(async move {
while let Some(message) = reader.next().await {
println!("{message}");
}
});
room.perform("speak", json!({ "body": "Hello!" })).await?;
room.unsubscribe().await?;
client.close().await;Two things are pluggable. A Transport carries bytes: the built-in
WebSocketTransport speaks RFC 6455 over tokio-tungstenite behind the default
websocket feature, and any other WebSocket library can be dropped in behind the same
trait with ClientBuilder::transport. Without the feature and without a transport,
ClientBuilder::build returns Error::NoTransport. A Protocol speaks one Action Cable
wire format, negotiated as one WebSocket subprotocol: V1Json implements
actioncable-v1-json, and a new format is a new Protocol rather than a fork of this
client. ClientBuilder::protocols offers several, and the server picks the one it
knows.
Where the Go client takes a context, this one takes nothing: Client::connect and
Client::subscribe wait until the server answers or the client stops, and a caller
who wants a deadline wraps the call in tokio::time::timeout. Dropping either future
is safe. The client keeps running — Client::last_error says what it is failing on —
and a subscription the server never confirmed is forgotten.
A client that stops for good says so through Client::done and Client::err: the
server hung up and said not to come back, the attempts
ClientBuilder::max_attempts allows ran out, or
ClientBuilder::stop_on_error recognized a failure no reconnect can repair.
Where the Go client takes callbacks, this one offers both: a stream of Events on
every Subscription, and SubscribeRequest for the callback form on top of the
same stream. Headers that expire come from a HeaderProvider, which a closure
returning a future satisfies. Nothing here logs through a logger of its own; the
client’s chatter goes to tracing.
The test-support feature adds actioncable::test_support, an in-memory transport a
test plays the server on, for testing code built on this client without a network.
Modules§
- test_
support - In-memory connections a test can play the server on, and a made-up protocol that stamps
everything it encodes so a test can tell which protocol the client settled on. Behind the
test-supportfeature, for this crate’s own tests and for the tests of anything built on it.
Structs§
- Client
- One connection to an Action Cable server and the subscriptions running over it. Build
one with
builder, start it withconnect, and hang up withclose. Handles are cheap to clone and share the connection. - Client
Builder - Configures a
Client. Nothing touches the network untilClient::connect. - Command
- A client-to-server message.
datacarries the already encoded action payload and is only set forCommandName::Message. - Dial
Options - What the client needs the transport to negotiate: the subprotocols its protocols speak, most preferred first, and the headers that authenticate the request, a cookie or a token, since an Action Cable server authorizes the upgrade request itself.
- Identifier
- Names one subscription: a channel and the params that go with it, like the id of the record the channel streams for.
- Incoming
- A decoded server-to-client frame.
reasonandreconnectare only set onKind::Disconnect,messageonKind::MessageandKind::Ping, and the identifier is empty on the frames that concern the connection rather than a subscription. AKind::Messageframe with nomessageis dropped and logged rather than delivered empty, which is where this client parts from the Go one. - Message
- The undecoded payload a channel broadcast or transmitted, exactly as it came off the
wire. Its shape is entirely up to the channel, so
decodeit into the type you expect. - Subscribe
Request - What to subscribe to, and what to do when its connection changes. The callbacks mirror
the Go client’s
OnConnected,OnDisconnectedandOnRejected; the same events also arrive onSubscription::next_event, so use whichever reads better. A bareIdentifierconverts into a request with no callbacks, which is whatClient::subscribetakes most of the time. - Subscription
- One channel subscription on a client. Read what the channel sends with
next, watch the connection withnext_event, and talk back withperformorsend. - V1Json
- The
actioncable-v1-jsonprotocol: JSON objects in text frames, keyed bycommandgoing out and bytypecoming in. - WebSocket
Transport - The built-in transport: tokio-tungstenite over rustls, trusting the platform’s root
certificates. It handles the upgrade handshake, answers pings, and reassembles
fragmented messages. The request carries
User-Agent: actioncable/<version>unless the caller set one, and never negotiates extensions.
Enums§
- Command
Name - The verb of a client-to-server command.
- Disconnect
Reason - Why an Action Cable server hung up. Rails names four; anything else it might send in the
future arrives as
Other. - Error
- Everything a caller can get back from a cable. It is
Clonebecause a client that stopped for good hands the same failure to everyone who asks it afterwards. - Event
- What happened to a subscription’s connection. Some channels only send what’s new, so a reconnect can leave a gap, and only the client knows a reconnect happened.
- Kind
- The type of a server-to-client frame.
Constants§
- SUBPROTOCOL_
UNSUPPORTED - The sentinel an Action Cable server names when it speaks none of the subprotocols offered. The client offers it last on every handshake, the way Rails’ own clients do, so a server with nothing in common can say so outright instead of leaving the subprotocol blank.
- SUBPROTOCOL_
V1_ JSON - The subprotocol every Rails Action Cable server speaks.
Traits§
- Conn
- One live connection. The client reads from one task and writes from another, one write
at a time, and may call
closeconcurrently with either. Closing has to interrupt a read in flight so the reader learns the connection is gone. - Header
Provider - Builds the headers for a dial, asked on every dial rather than once. A client reconnects on its own for as long as it runs, which is longer than a credential that expires lives, and a reconnect carrying the token the first dial used would be turned down for good.
- Protocol
- Translates between Action Cable commands and the bytes on the wire. It is the seam where an Action Cable protocol plugs in.
- Transport
- Dials the network connection a client talks over. It is the seam where a network handler
plugs in: the built-in
WebSocketTransportspeaks RFC 6455 over tokio-tungstenite, and wrapping another WebSocket crate, or an in-memory pipe for tests, means implementing this andConnand nothing else.