syncthing_async/
client.rs1use crate::Fallible;
2use crate::event_stream::EventStream;
3use http::Method;
4use http::header::HeaderValue;
5use http::uri::Authority;
6use reqwest::Client as HttpClient;
7use serde::Serialize;
8use serde::de::DeserializeOwned as Deserialize;
9use std::collections::HashMap;
10use syncthing_types::events::{Event, EventType};
11use syncthing_types::utils::construct_uri;
12use syncthing_types::{API_DEFAULT_AUTHORITY, Timestamp};
13use syncthing_types::{API_HEADER_KEY, routes::*};
14use syncthing_types::{EMPTY_EVENT_SUBSCRIPTION, system};
15use syncthing_types::{cluster, utils};
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 get<D: Deserialize, T: AsRef<[u8]> + 'static>(
41 &self,
42 path_and_query: T,
43 ) -> Fallible<D> {
44 let url = construct_uri(&self.authority, path_and_query)?.to_string();
45 let resp = self
46 .client
47 .request(Method::GET, url)
48 .header(API_HEADER_KEY, HeaderValue::from_str(&self.api_key)?)
49 .send()
50 .await?
51 .error_for_status()?;
52 Ok(resp.json().await?)
53 }
54
55 pub(crate) async fn post<S: Serialize, T: AsRef<[u8]> + 'static>(
56 &self,
57 path_and_query: T,
58 body: &S,
59 ) -> Fallible<()> {
60 let url = construct_uri(&self.authority, path_and_query)?.to_string();
61 self.client
62 .request(Method::POST, url)
63 .body(serde_json::to_string(body)?)
64 .header(API_HEADER_KEY, HeaderValue::from_str(&self.api_key)?)
65 .send()
66 .await?
67 .error_for_status()?;
68 Ok(())
69 }
70
71 pub async fn get_all_events(
72 &self,
73 since: Option<u64>,
74 limit: Option<u64>,
75 ) -> Fallible<Vec<Event>> {
76 self.get_events(since, limit, &EMPTY_EVENT_SUBSCRIPTION)
77 .await
78 }
79
80 pub async fn get_events(
81 &self,
82 since: Option<u64>,
83 limit: Option<u64>,
84 events: impl AsRef<[EventType]>,
85 ) -> Fallible<Vec<Event>> {
86 let path_and_query = utils::construct_event_path_and_query(since, limit, events)?;
87 self.get(path_and_query).await
88 }
89
90 pub fn subscribe_to(self, events: impl Into<Vec<EventType>>) -> EventStream {
91 EventStream::new(self, events.into())
92 }
93
94 pub fn subscribe_to_all(self) -> EventStream {
95 EventStream::new(self, EMPTY_EVENT_SUBSCRIPTION.clone())
96 }
97
98 pub async fn browse(&self, pattern: Option<String>) -> Fallible<Vec<String>> {
99 if let Some(pattern) = pattern {
100 self.get(format!("{}?current={}", SYSTEM_BROWSE, pattern))
101 .await
102 } else {
103 self.get(SYSTEM_BROWSE).await
104 }
105 }
106
107 pub async fn get_connections(&self) -> Fallible<system::Connections> {
108 self.get(SYSTEM_CONNECTIONS).await
109 }
110
111 pub async fn get_discovery_cache(&self) -> Fallible<system::Discovery> {
112 self.get(SYSTEM_DISCOVERY).await
113 }
114
115 pub async fn get_log(&self, since: Option<Timestamp>) -> Fallible<system::Log> {
116 if let Some(since) = since {
117 self.get(format!("{}?since={}", SYSTEM_LOG, since.to_rfc3339()))
118 .await
119 } else {
120 self.get(SYSTEM_LOG).await
121 }
122 }
123
124 pub async fn get_errors(&self) -> Fallible<system::Error> {
125 self.get(SYSTEM_ERROR).await
126 }
127
128 pub async fn clear_errors(&self) -> Fallible<()> {
129 self.post(SYSTEM_ERROR_CLEAR, &()).await
130 }
131
132 pub async fn get_loglevels_info(&self) -> Fallible<system::LogLevelsInfo> {
133 self.get(SYSTEM_LOGLEVELS).await
134 }
135
136 pub async fn get_paths(&self) -> Fallible<HashMap<String, String>> {
137 self.get(SYSTEM_PATHS).await
138 }
139
140 pub async fn ping(&self) -> Fallible<system::Ping> {
141 self.get(SYSTEM_PING).await
142 }
143
144 pub async fn status(&self) -> Fallible<system::Status> {
145 self.get(SYSTEM_STATUS).await
146 }
147
148 pub async fn get_upgrade_info(&self) -> Fallible<system::UpgradeInfo> {
149 self.get(SYSTEM_UPGRADE).await
150 }
151
152 pub async fn get_version_info(&self) -> Fallible<system::VersionInfo> {
153 self.get(SYSTEM_VERSION).await
154 }
155
156 pub async fn get_cluster_pending_devices(&self) -> Fallible<cluster::PendingDevices> {
157 self.get(CLUSTER_PENDING_DEVICES).await
158 }
159}