pub struct Builder<D> { /* private fields */ }Expand description
Builds a Federation.
Implementations§
Source§impl<D: Clone + Send + Sync + 'static> Builder<D>
impl<D: Clone + Send + Sync + 'static> Builder<D>
Sourcepub fn origin(self, origin: Url) -> Self
pub fn origin(self, origin: Url) -> Self
Serve every request in origin’s URIs, whatever host it came to: for
an application with one host.
Sourcepub fn origin_with(
self,
origin: impl Fn(&str, &D) -> Option<Url> + Send + Sync + 'static,
) -> Self
pub fn origin_with( self, origin: impl Fn(&str, &D) -> Option<Url> + Send + Sync + 'static, ) -> Self
The canonical origin for a request to a host, or None for a host
Ojak should not answer for. A host this maps to the canonical origin
is one of its aliases: its IRIs are ours, and its handles are.
Sourcepub fn actor<F, Fut, E>(self, kind: &str, template: &str, load: F) -> Self
pub fn actor<F, Fut, E>(self, kind: &str, template: &str, load: F) -> Self
Serve actors of kind at template, whose one expression, if it has
one, is the actor’s identifier.
Sourcepub fn object<F, Fut, E>(self, kind: &str, template: &str, load: F) -> Self
pub fn object<F, Fut, E>(self, kind: &str, template: &str, load: F) -> Self
Serve objects of kind at template, whose expressions the
dispatcher receives by name.
Sourcepub fn object_alias(self, kind: &str, template: &str) -> Self
pub fn object_alias(self, kind: &str, template: &str) -> Self
Serve the objects of kind at template as well, and recognise it
in Context::parse_uri and Context::parse_object: another path
the same objects are known by, such as Mastodon’s /@{username}/{id}
beside /users/{username}/statuses/{id}. URIs are still built from
the template kind was registered with. The dispatcher receives this
template’s values, so it has to name every expression the first
template does, and may name more.
Sourcepub fn collection_alias(self, kind: &str, template: &str) -> Self
pub fn collection_alias(self, kind: &str, template: &str) -> Self
Serve the collection kind at template as well, and recognise it in
Context::parse_uri: another path the same collection is known by,
such as Mastodon’s /@{username}/followers beside
/users/{username}/followers. The collection is still named by the
template kind was registered with, in its id and its pages’
links. The alias names the owner in as many expressions as that
template does: one, or none.
Sourcepub fn collection(
self,
kind: &str,
template: &str,
collection: Collection<D>,
) -> Self
pub fn collection( self, kind: &str, template: &str, collection: Collection<D>, ) -> Self
Serve the collection kind at template, whose one expression, if it
has one, is the identifier of what it belongs to.
Serve what is registered as kind only to requests authorize allows.
It receives the verified signer of the request, if it was signed and
signed fetches are configured. A request it refuses is 401.
Sourcepub fn guard<F, Fut, E>(self, kind: &str, guard: F) -> Self
pub fn guard<F, Fut, E>(self, kind: &str, guard: F) -> Self
Serve what is registered as kind only as guard says: to all, or
refused as unauthorized (401), forbidden (403) or not there (404).
Unlike Builder::authorize, nothing is verified before it is asked:
the guard asks Context::signing or Context::signer when it
needs to know who signed, so a guard that lets everyone through costs
no signature check, nor a key fetched to make one.
Sourcepub fn key_pairs<F, Fut, E>(self, keys: F) -> Self
pub fn key_pairs<F, Fut, E>(self, keys: F) -> Self
Where actors’ public keys come from, read by Context::actor_keys.
Sourcepub fn handle<F, Fut, E>(self, lookup: F) -> Self
pub fn handle<F, Fut, E>(self, lookup: F) -> Self
Which actor a WebFinger handle’s username names.
Sourcepub fn map_alias<F, Fut, E>(self, lookup: F) -> Self
pub fn map_alias<F, Fut, E>(self, lookup: F) -> Self
Which actor another URL of ours, such as a profile page, names, for WebFinger.
Sourcepub fn webfinger_links(
self,
links: impl Fn(&Context<D>, &ActorRef, &Value) -> Vec<Value> + Send + Sync + 'static,
) -> Self
pub fn webfinger_links( self, links: impl Fn(&Context<D>, &ActorRef, &Value) -> Vec<Value> + Send + Sync + 'static, ) -> Self
Links a WebFinger answer carries beside self and profile-page,
such as Mastodon’s subscribe template.
Sourcepub fn nodeinfo<F, Fut, E>(self, nodeinfo: F) -> Self
pub fn nodeinfo<F, Fut, E>(self, nodeinfo: F) -> Self
Serve NodeInfo, 2.0 and 2.1, from nodeinfo.
Sourcepub fn signed_fetch<K, F, Fut, E>(
self,
fetcher: Arc<Fetcher>,
kv: K,
key_ttl: Duration,
key: F,
) -> Self
pub fn signed_fetch<K, F, Fut, E>( self, fetcher: Arc<Fetcher>, kv: K, key_ttl: Duration, key: F, ) -> Self
Verify signed GETs, for Context::signer and authorize: keys are
fetched with fetcher, signed with the key key returns when there is
one, and kept in kv for key_ttl.
Sourcepub fn fetcher_for(
self,
fetcher: impl Fn(&D) -> Arc<Fetcher> + Send + Sync + 'static,
) -> Self
pub fn fetcher_for( self, fetcher: impl Fn(&D) -> Arc<Fetcher> + Send + Sync + 'static, ) -> Self
The fetcher for a request’s data, in place of the one given to
Builder::signed_fetch: an application serving several instances
fetches with each one’s own. Call after signed_fetch.
Sourcepub fn kv_for<K: KvStore>(
self,
kv: impl Fn(&D) -> Arc<K> + Send + Sync + 'static,
) -> Self
pub fn kv_for<K: KvStore>( self, kv: impl Fn(&D) -> Arc<K> + Send + Sync + 'static, ) -> Self
The key-value store for a request’s data, in place of the one given
to Builder::signed_fetch: an application serving several
instances keeps each one’s cached keys and the activities it has seen
in that instance’s own store, such as its own namespace of a shared
Redis. Call after signed_fetch.
Sourcepub fn known_key<F, Fut, E>(self, known: F) -> Self
pub fn known_key<F, Fut, E>(self, known: F) -> Self
A key the application already holds for a key ID, tried before the
key-value store and a fetch: an application that stores remote
actors’ keys, as Mastodon’s schema does, need not fetch them again. A
key that does not verify is fetched fresh. Call after signed_fetch.
Sourcepub fn key_fetched<F, Fut>(self, hook: F) -> Self
pub fn key_fetched<F, Fut>(self, hook: F) -> Self
See the document of an actor Ojak fetched for its key, once the key
has verified a request: an application that stores actors stores this
one, so a new actor’s first activity does not fetch it twice. Call
after signed_fetch.
Sourcepub fn on_any<F, Fut, E>(self, listen: F) -> Self
pub fn on_any<F, Fut, E>(self, listen: F) -> Self
Run listen for every activity no typed listener is registered for,
read as whatever it is: for an application with a dispatcher of its
own, which reads Received::vouched.
Sourcepub fn inbox(self, kind: &str, template: &str) -> Self
pub fn inbox(self, kind: &str, template: &str) -> Self
Receive activities at template, the inbox of the actors of kind,
whose one expression is the actor’s identifier; or, for an actor
whose own template has no expression, such as an instance actor at
/actor, with none.
Receive activities at path, the shared inbox.
Sourcepub fn on<T, F, Fut, E>(self, listen: F) -> Self
pub fn on<T, F, Fut, E>(self, listen: F) -> Self
Run listen for every activity of type T an inbox receives from a
sender Ojak has authenticated. Types with no listener are accepted
and dropped.
Sourcepub fn read_inbox_as_written(self) -> Self
pub fn read_inbox_as_written(self) -> Self
Hand listeners each activity as its sender wrote it, without JSON-LD
processing: its @context removed and what it embeds reduced to what
the sender can vouch for, as always, but its terms left as spelled.
By default an activity is expanded and compacted against ojak’s context first, so that a sender’s aliases, prefixes and extension terms read as ojak’s vocabulary expects. That is what a listener typed to a vocabulary type relies on. An application that reads the JSON itself, as Mastodon reads it, needs none of it, and this skips the work — and the refusal of a document whose context cannot be processed.
Sourcepub fn linked_data_before_proof(self) -> Self
pub fn linked_data_before_proof(self) -> Self
Check a forwarded activity’s Linked Data signature before its FEP-8b32 proof, rather than after.
An activity signed by a server other than its actor’s is taken on its
actor’s proof by default, and on its Linked Data signature only when it
has no proof that holds: a proof is the cheaper check, needing no
JSON-LD processing. Mastodon and Fedify check the signature first, and
what an activity is taken on decides whether it can be passed on
(Received::vouched_by): Mastodon passes on only an activity taken on
its Linked Data signature. An application that forwards as Mastodon
does asks for this, so that an activity carrying both is taken on its
signature. A request signed by the actor’s own server, and one whose
signature does not verify, are unaffected.
Sourcepub fn blocked<F, Fut, E>(self, blocked: F) -> Self
pub fn blocked<F, Fut, E>(self, blocked: F) -> Self
Whether activities from host are refused, asked before any key is
fetched for them. A refused activity is answered 202 and dropped.
A request signed with a key on host is refused too, before the key
is looked for: its signer is not verified, an inbox POST is answered
as one that does not verify, and a GET’s signing is
Signing::Blocked.
Sourcepub fn remote_contexts<F, Fut, E>(self, limits: Limits, load: F) -> Self
pub fn remote_contexts<F, Fut, E>(self, limits: Limits, load: F) -> Self
Check a Linked Data Signature over contexts ojak does not ship, as
Mastodon does: load returns the context an IRI names, the body
crate::contexts::fetch returns, from the application’s cache or
fetched with its client (crate::contexts::fetch_cached does both).
Without it, an activity naming such a context is not taken on its
signature, and is fetched from its origin instead.
Only that check loads contexts, and only within limits; the
activity is then read over the same contexts, so that what it is
taken to say is what was signed.
Sourcepub fn on_unverified<F, Fut>(self, hook: F) -> Self
pub fn on_unverified<F, Fut>(self, hook: F) -> Self
See every activity whose sender could not be authenticated, which is where an application removes an actor whose Delete it could not verify because the actor, key and all, is gone.
Sourcepub fn inbox_queue(
self,
queue: impl Fn(&D) -> Option<SharedQueue> + Send + Sync + 'static,
) -> Self
pub fn inbox_queue( self, queue: impl Fn(&D) -> Option<SharedQueue> + Send + Sync + 'static, ) -> Self
The queue activities wait in for an InboxWorker, for the data of a
request: an application with a database per tenant has a queue per
tenant. Without one, or when it gives None, listeners run inside the
request.
Sourcepub fn gateway<F, Fut, E>(self, load: F) -> Self
pub fn gateway<F, Fut, E>(self, load: F) -> Self
Serve the portable objects (FEP-ef61) this server is a gateway for,
at /.well-known/apgateway/{did}/{+path}. load returns the object
an ap URI names, as the signed document the application stored: its
proof covers it, and Ojak serves it as it is. An object that is not
public is the application’s to refuse, as for any dispatcher.
What is served is checked first, as whoever fetches it will check it:
a document whose id is another object is answered 404, and one
whose proof does not verify, 500, both reported to on_error. A
collection may have no proof. A signed Tombstone is served with 410;
Found::Gone serves an unsigned one, which says the object is gone
but that nobody can take for its owner’s word.
Sourcepub fn gateway_media<F, Fut, E>(self, load: F) -> Self
pub fn gateway_media<F, Fut, E>(self, load: F) -> Self
Serve the media portable objects refer to by hashlink (FEP-ef61), at
/.well-known/apgateway/hl:zQm…. load returns what the hashlink
names; it is served only if it is that, since it is checked against
the digest wherever it is fetched, and a mismatch is reported to
on_error and answered 500. Anyone who knows a digest can fetch what
it names: media with an audience is the application’s to refuse.
Sourcepub fn gateway_inbox<F, Fut, E>(self, inbox_for: F) -> Self
pub fn gateway_inbox<F, Fut, E>(self, inbox_for: F) -> Self
Accept deliveries to portable inboxes: inbox_for maps the ap URI
of an inbox POSTed to at /.well-known/apgateway/… to the actor the
application hosts it for, who the listeners see as the recipient, and
the gateways that actor lists, which what arrives is forwarded to.
An inbox it maps to None is answered 404.
Sourcepub fn forward<F, Fut, E>(self, forward: F) -> Self
pub fn forward<F, Fut, E>(self, forward: F) -> Self
Forward what arrives to where it has to go on to: a portable actor’s
other gateways, as FEP-ef61 asks, and the members of collections of
ours an activity concerning something of ours is addressed to, as
ActivityPub asks (§7.1.2). forward is called once for each activity
and kind of forward, however many times it arrives, and sends it.
Without it, nothing is forwarded.
Sourcepub fn on_error(self, report: impl Fn(&Error) + Send + Sync + 'static) -> Self
pub fn on_error(self, report: impl Fn(&Error) + Send + Sync + 'static) -> Self
See every error a dispatcher returns, which is otherwise a bare 500.
Sourcepub fn build(self) -> Result<Federation<D>, BuildError>
pub fn build(self) -> Result<Federation<D>, BuildError>
The federation.
§Errors
When there is no origin, a template is malformed, two templates could
match one path, a template claims a path Ojak serves itself, two
dispatchers share a kind, an actor or collection template has more
than one expression, or authorize names no kind.