kitsune2_bootstrap_client/
lib.rs

1//! A client for the Kitsune2 bootstrap server.
2
3#![deny(missing_docs)]
4
5use kitsune2_api::{AgentInfoSigned, DynVerifier, K2Error, K2Result, SpaceId};
6use std::sync::Arc;
7
8/// Send the agent info, for the given space, to the bootstrap server.
9///
10/// Note the `blocking_` prefix. This is a hint to the caller that if the function is used in
11/// an async context, it should be treated as a blocking operation.
12pub fn blocking_put(
13    server_url: &str,
14    agent_info: &AgentInfoSigned,
15) -> K2Result<()> {
16    let url = format!(
17        "{server_url}/bootstrap/{}/{}",
18        &agent_info.space, &agent_info.agent
19    );
20
21    let encoded = agent_info.encode()?;
22    ureq::put(&url)
23        .send_string(&encoded)
24        .map_err(|e| K2Error::other_src("Failed to put agent info", e))?;
25
26    Ok(())
27}
28
29/// Get all agent infos from the bootstrap server for the given space.
30///
31/// Note the `blocking_` prefix. This is a hint to the caller that if the function is used in
32/// an async context, it should be treated as a blocking operation.
33pub fn blocking_get(
34    server_url: &str,
35    space: SpaceId,
36    verifier: DynVerifier,
37) -> K2Result<Vec<Arc<AgentInfoSigned>>> {
38    let url = format!("{server_url}/bootstrap/{}", space);
39
40    let encoded = ureq::get(&url)
41        .call()
42        .map_err(K2Error::other)?
43        .into_string()
44        .map_err(K2Error::other)?;
45
46    Ok(AgentInfoSigned::decode_list(&verifier, encoded.as_bytes())?
47        .into_iter()
48        .filter_map(|l| {
49            l.inspect_err(|err| {
50                tracing::debug!(?err, "failure decoding bootstrap agent info");
51            })
52            .ok()
53        })
54        .collect::<Vec<_>>())
55}