Rust Urbit HTTP API
This library wraps the Urbit ship http interface exposing it as an easy-to-use Rust crate.
All implementation details such as auth cookies, EventSource connections, tracking message ids, and other such matters are automatically handled for you, and as enables a greatly improved experience in writing Rust apps that interact with Urbit ships.
This crate currently enables devs to:
- Authorize oneself and open a channel with the ship.
- Subscribe to any app/path so that one can read the events currently taking place inside of the ship.
- Issue
Poke
s to apps.
Design
There are 3 main structs that this library exposes for interacting with an Urbit ship:
ShipInterface
Channel
Subscription
A Subscription
is created by a Channel
which is created by a ShipInterface
. In other words, first you need to connect to an Urbit ship (using ShipInterface
) before you can initiate a messaging Channel
, before you can create a Subscription
to an app/path.
ShipInterface
The ShipInterface
exposes a few useful methods that will be useful when creating apps.
The more commonly used methods below these allow you to create a new ShipInterface
(thereby authorizing yourself with the ship), and create a new Channel
.
/// Logs into the given ship and creates a new `ShipInterface`.
/// `ship_url` should be `http://ip:port` of the given ship. Example:
/// `http://0.0.0.0:8080`. `ship_code` is the code acquire from your ship
/// by typing `+code` in dojo.
;
/// Create a `Channel` using this `ShipInterface`
;
You also have the ability to scry and run threads via spider.
/// Send a scry using the `ShipInterface`
;
/// Run a thread via spider using the `ShipInterface`
;
Channel
Channel
is the most useful struct, because it holds methods related to interacting with both pokes and subscriptions.
It is instructive to look at the definition of the Channel
struct to understand how it works:
// A Channel which is used to interact with a ship
Once a Channel
is created, an EventSource
connection is created with the ship on a separate thread. This thread accepts all of the incoming events, and queues them on a (Rust) unbounded channel which is accessible internally via the event_receiver
. This field itself isn't public, but processing events in this crate is handled with a much higher-level interface for the app developer.
Take note that a Channel
has a subscription_list
. As you will see below, each Channel
exposes methods for creating subscriptions, which automatically get added to the subscription_list
.
Once Subscription
s are created/added to the list, the Channel
will evidently start to receive event messages via SSE (which will be queued for reading in the event_receiver
).
From the app developer's perspective, all one has to do is call the parse_event_messages()
method on your Channel
, and all of the queued events will be processed and passed on to the correct Subscription
's message_list
. This is useful once multiple Subscriptions
are created on a single channel, as the messages will be pre-sorted automatically for you.
Once the event messages are parsed, then one can simply call the find_subscription
method in order to interact with the Subscription
and read its messages.
The following are the useful methods exposed by a Channel
:
/// Sends a poke over the channel
;
/// Create a new `Subscription` and thus subscribes to events on the ship with the provided app/path.
;
/// Parses SSE messages for this channel and moves them into
/// the proper corresponding `Subscription`'s `message_list`.
;
/// Finds the first `Subscription` in the list which has a matching
/// `app` and `path`;
;
/// Finds the first `Subscription` in the list which has a matching
/// `app` and `path`, removes it from the list, and tells the ship
/// that you are unsubscribing.
;
/// Deletes the channel
;
Subscription
As mentioned in the previous section, a Subscription
contains it's own message_list
field where messages are stored after a Channel
processes them.
From an app developer's perspective, this is the only useful feature of the Subscription
struct. Once acquired, it is used simply to read the messages.
To improve the message reading experience, the Subscription
struct exposes a useful method:
/// Pops a message from the front of `Subscription`'s `message_list`.
/// If no messages are left, returns `None`.
;
Code Examples
Poke Example
This example displays how to connect to a ship using a ShipInterface
, opening a Channel
, issuing a poke
over said channel, and then deleting the Channel
to finish.
// Import the `ShipInterface` struct
use ShipInterface;
Subscription Example
This example shows how to create, interact with, and delete a Subscription
. In this scenario we desire to read messages from our Subscription
for 10 seconds, and then perform cleanup.
use thread;
use Duration;
use ShipInterface;
This library was created by ~mocrux-nomdep(Robert Kornacki).