syncthing_async/
client.rs

1use crate::Fallible;
2use crate::events::EventStream;
3use http::Method;
4use http::header::HeaderValue;
5use http::uri::{Authority, Parts as UriParts, PathAndQuery, Scheme, Uri};
6use reqwest::Client as HttpClient;
7use serde::de::DeserializeOwned as Deserialize;
8use syncthing_types::events::{Event, EventType};
9use syncthing_types::routes::*;
10use syncthing_types::system;
11use syncthing_types::utils;
12
13static API_HEADER_KEY: &str = "X-API-Key";
14static API_DEFAULT_AUTHORITY: &str = "127.0.0.1:8384";
15static EMPTY_EVENT_SUBSCRIPTION: Vec<EventType> = Vec::new();
16
17pub struct Client {
18    client: HttpClient,
19    authority: Authority,
20    api_key: String,
21}
22
23impl Client {
24    pub fn new(api_key: impl Into<String>) -> Self {
25        Self {
26            client: HttpClient::new(),
27            authority: Authority::from_static(API_DEFAULT_AUTHORITY),
28            api_key: api_key.into(),
29        }
30    }
31
32    pub fn with_authority(api_key: impl Into<String>, authority: Authority) -> Self {
33        Self {
34            client: HttpClient::new(),
35            authority,
36            api_key: api_key.into(),
37        }
38    }
39
40    pub(crate) async fn request<D: Deserialize, T: AsRef<[u8]> + 'static>(
41        &self,
42        method: Method,
43        path_and_query: T,
44    ) -> Fallible<D> {
45        let mut uri_parts = UriParts::default();
46        uri_parts.authority = Some(self.authority.clone());
47        uri_parts.scheme = Some(Scheme::HTTP);
48        uri_parts.path_and_query = Some(PathAndQuery::from_maybe_shared(path_and_query)?);
49        let uri = Uri::from_parts(uri_parts)?;
50        let resp = self
51            .client
52            .request(method, uri.to_string())
53            .header(API_HEADER_KEY, HeaderValue::from_str(&self.api_key)?)
54            .send()
55            .await?
56            .error_for_status()?;
57        Ok(resp.json().await?)
58    }
59
60    pub async fn get_all_events(
61        &self,
62        since: Option<u64>,
63        limit: Option<u64>,
64    ) -> Fallible<Vec<Event>> {
65        self.get_events(since, limit, &EMPTY_EVENT_SUBSCRIPTION)
66            .await
67    }
68
69    pub async fn get_events(
70        &self,
71        since: Option<u64>,
72        limit: Option<u64>,
73        events: impl AsRef<[EventType]>,
74    ) -> Fallible<Vec<Event>> {
75        let path_and_query = utils::construct_event_url(since, limit, events)?;
76        self.request(Method::GET, path_and_query).await
77    }
78
79    pub fn subscribe_to(self, events: impl Into<Vec<EventType>>) -> EventStream {
80        EventStream::new(self, events.into())
81    }
82
83    pub fn subscribe_to_all(self) -> EventStream {
84        EventStream::new(self, EMPTY_EVENT_SUBSCRIPTION.clone())
85    }
86
87    pub async fn get_system_connections(&self) -> Fallible<system::Connections> {
88        self.request(Method::GET, SYSTEM_CONNECTIONS_PATH).await
89    }
90
91    pub async fn get_system_debug(&self) -> Fallible<system::DebugInfo> {
92        self.request(Method::GET, SYSTEM_DEBUG_PATH).await
93    }
94
95    pub async fn get_system_discovery(&self) -> Fallible<system::Discovery> {
96        self.request(Method::GET, SYSTEM_DISCOVERY_PATH).await
97    }
98
99    pub async fn get_system_log(&self) -> Fallible<system::Log> {
100        self.request(Method::GET, SYSTEM_LOG_PATH).await
101    }
102
103    pub async fn get_system_error(&self) -> Fallible<system::Error> {
104        self.request(Method::GET, SYSTEM_ERROR_PATH).await
105    }
106
107    pub async fn get_system_ping(&self) -> Fallible<system::Ping> {
108        self.request(Method::GET, SYSTEM_PING_PATH).await
109    }
110
111    pub async fn get_system_upgrade(&self) -> Fallible<system::UpgradeInfo> {
112        self.request(Method::GET, SYSTEM_UPGRADE_PATH).await
113    }
114
115    pub async fn get_system_version(&self) -> Fallible<system::Version> {
116        self.request(Method::GET, SYSTEM_VERSION_PATH).await
117    }
118}