Bidirectional Subscriptions (Websockets)

Currently XRPC endpoints can be declared as queries (client to server), procedures (client to server), or subscriptions (server to client).

However the mechanism for subscriptions, websockets, supports bidirectional communication. Additionally for any stateful service websockets significantly outperform traditional http POST requests due to the persistent nature of their connection.

The approach I’ve used for corvus.page, chaos.soccer, and deception.town is to establish a set of backchannel frames. This is a lexicon union type that declare the messages that can be sent from client to server on the subscription connection. However this is documented purely in the description of the xprc subscription.

What I’d propose is an extension to the subscription type that allows for these messages to become first class members. The extension would do the following.

  1. Define the messages that a client can send to the server on the websocket
  2. Define a authorization (beyond what is required for the basic subscription) that is required to send data.

On the second point in particular there are a number of cases where the subscription may carry public data from the server to the client, but carry private data from the client to the server. This requires us to authenticate for bidirectional sending but not for a standard subscription.

2 Likes

I read this and it made me think about the newly updated Tiles Protocol, specifically data passing:

I agree that it would be useful to have bi-directional event-streams and be able to declare not just a subscription but a chat or conversation type of XRPC interaction.

For authentication/authorization, that’s just an error that the subscription or websocket can raise, as for how you do the websockets, you may want to make use of short-lived signed parameters for the subscription, so like you send a request to an API to get back correct params + user context + signature + timing (to prevent replays), and then the subscription accepts that result as an input parameter, handler for the subscription then checks that and writes back an error frame if needed to say something like “AuthenticationRequired”

I’m not 100% sure if subscriptions can be called with proxying but I don’t think so, so you’d probably do a proxy on the procedure and then call the subscription with the resulting token as a param.

1 Like