Skip to content

Transports

Choosing between HTTP batch, WebSocket, MessagePort, and custom transports, and the session model they share.

Updated View as Markdown

Cap’n Web runs over any bidirectional stream of discrete messages. Four options ship in the box, and you can write your own.

Transport Long-lived Server can call client Best for
HTTP batch No No A burst of calls, then done. Stateless edges.
WebSocket Yes Yes Interactive apps, subscriptions, callbacks.
MessagePort Yes Yes Web Workers, iframes, same-process boundaries.
Custom Up to you Yes Anything else with two directions.

Sessions are symmetric

Sessions are entirely symmetric: neither side is defined as the “client” nor the “server”. Each side can optionally expose a “main interface” to the other. In typical scenarios with a logical client and server, the server exposes a main interface and the client does not.

The words “client” and “server” appear throughout these docs only as a convention to make explanations natural. “Client” generally means the caller of an RPC or the importer of a stub; “server” means the callee or exporter.

Disposal ends the session

Disposing the root stub of a session closes the connection:

{
  using api = newWebSocketRpcSession<MyApi>('wss://example.com/api');
  // ... use api ...
} // connection closed here

Only the root stub behaves this way. Disposing any other stub releases the object it points at on the peer, but leaves the connection open:

using api = newWebSocketRpcSession<PublicApi>('wss://example.com/api');

{
  using authed = api.authenticate(apiToken);
  // ...
} // AuthedApi released on the server; the session is still up.

For HTTP batch, the session ends when the batch completes, and all stubs are implicitly disposed at that point. See Disposal.

Session state is in-memory and lasts exactly as long as the session; there is nothing to persist and no session store to run. Sessions & reconnection covers what that means for reconnecting, versioning and load balancing.

Message framing

The protocol operates on a bidirectional stream of discrete messages, each a single JSON value. The protocol itself does not define framing: that is the transport’s job.

  • Transports with native framing (WebSocket, MessagePort) map one transport message to one RPC message.
  • The built-in HTTP transport is newline-delimited, packing a series of messages into a single request or response body. An empty body means zero messages.

See the wire protocol reference for the full picture.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close