1use crate::Error;
4use log::debug;
5use serde::Serialize;
6
7pub mod dav;
9pub mod file;
11pub mod models;
13pub mod session;
15pub mod share;
17pub mod site;
19pub mod uri;
21pub mod user;
23pub mod workflow;
25
26#[derive(Debug, Clone)]
28pub struct ApiV4Client {
29 pub base_url: String,
31 pub http_client: reqwest::Client,
33 pub token: Option<String>,
35}
36
37impl ApiV4Client {
38 pub fn new(base_url: &str) -> Self {
40 Self {
41 base_url: base_url.to_string(),
42 http_client: reqwest::Client::new(),
43 token: None,
44 }
45 }
46
47 pub fn set_token(&mut self, token: String) {
49 self.token = Some(token);
50 }
51
52 fn get_url(&self, endpoint: &str) -> String {
54 format!(
55 "{}/api/v4/{}",
56 self.base_url.trim_end_matches('/'),
57 endpoint.trim_start_matches('/')
58 )
59 }
60
61 pub async fn get<T>(&self, endpoint: &str) -> Result<T, Error>
63 where
64 T: serde::de::DeserializeOwned + std::fmt::Debug,
65 {
66 let url = self.get_url(endpoint);
67 let mut request = self.http_client.get(&url);
68
69 if let Some(token) = &self.token {
70 request = request.bearer_auth(token);
71 }
72 debug!("GET URL: {}", url);
73
74 let response = request.send().await?;
75 let status = response.status();
76
77 if !status.is_success() {
79 let raw_text = response.text().await?;
80 if let Ok(api_response) =
82 serde_json::from_str::<crate::ApiResponse<serde_json::Value>>(&raw_text)
83 && api_response.code != 0
84 {
85 return Err(Error::Api {
86 code: api_response.code,
87 message: api_response.msg,
88 });
89 }
90 return Err(Error::Api {
92 code: status.as_u16() as i32,
93 message: raw_text.trim().to_string(),
94 });
95 }
96
97 let raw_text = response.text().await?;
99
100 match serde_json::from_str::<T>(&raw_text) {
101 Ok(json) => {
102 debug!("Response status: {}, JSON: {:?}", status, json);
103 Ok(json)
104 }
105 Err(e) => {
106 debug!("JSON parse error: {}, raw response: {}", e, raw_text);
107 Err(Error::Json(e))
108 }
109 }
110 }
111
112 pub async fn post<T>(&self, endpoint: &str, body: &impl Serialize) -> Result<T, Error>
114 where
115 T: serde::de::DeserializeOwned + std::fmt::Debug,
116 {
117 let url = self.get_url(endpoint);
118 let mut request = self.http_client.post(&url).json(body);
119
120 if let Some(token) = &self.token {
121 request = request.bearer_auth(token);
122 }
123
124 debug!("POST URL: {}", url);
125
126 let response = request.send().await?;
127 let status = response.status();
128
129 if !status.is_success() {
131 let raw_text = response.text().await?;
132 if let Ok(api_response) =
133 serde_json::from_str::<crate::ApiResponse<serde_json::Value>>(&raw_text)
134 && api_response.code != 0
135 {
136 return Err(Error::Api {
137 code: api_response.code,
138 message: api_response.msg,
139 });
140 }
141 return Err(Error::Api {
142 code: status.as_u16() as i32,
143 message: raw_text.trim().to_string(),
144 });
145 }
146
147 let raw_text = response.text().await?;
148
149 match serde_json::from_str::<T>(&raw_text) {
150 Ok(json) => {
151 debug!("Response status: {}, JSON: {:?}", status, json);
152 Ok(json)
153 }
154 Err(e) => {
155 debug!("JSON parse error: {}, raw response: {}", e, raw_text);
156 Err(Error::Json(e))
157 }
158 }
159 }
160
161 pub async fn put<T>(&self, endpoint: &str, body: &impl Serialize) -> Result<T, Error>
163 where
164 T: serde::de::DeserializeOwned + std::fmt::Debug,
165 {
166 let url = self.get_url(endpoint);
167 let mut request = self.http_client.put(&url).json(body);
168
169 if let Some(token) = &self.token {
170 request = request.bearer_auth(token);
171 }
172 debug!("PUT URL: {}", url);
173
174 let response = request.send().await?;
175 let status = response.status();
176
177 if !status.is_success() {
179 let raw_text = response.text().await?;
180 if let Ok(api_response) =
181 serde_json::from_str::<crate::ApiResponse<serde_json::Value>>(&raw_text)
182 && api_response.code != 0
183 {
184 return Err(Error::Api {
185 code: api_response.code,
186 message: api_response.msg,
187 });
188 }
189 return Err(Error::Api {
190 code: status.as_u16() as i32,
191 message: raw_text.trim().to_string(),
192 });
193 }
194
195 let raw_text = response.text().await?;
196
197 match serde_json::from_str::<T>(&raw_text) {
198 Ok(json) => {
199 debug!("Response status: {}, JSON: {:?}", status, json);
200 Ok(json)
201 }
202 Err(e) => {
203 debug!("JSON parse error: {}, raw response: {}", e, raw_text);
204 Err(Error::Json(e))
205 }
206 }
207 }
208
209 pub async fn patch<T>(&self, endpoint: &str, body: &impl Serialize) -> Result<T, Error>
210 where
211 T: serde::de::DeserializeOwned + std::fmt::Debug,
212 {
213 let url = self.get_url(endpoint);
214 let mut request = self.http_client.patch(&url).json(body);
215
216 if let Some(token) = &self.token {
217 request = request.bearer_auth(token);
218 }
219 debug!("PATCH URL: {}", url);
220
221 let response = request.send().await?;
222 let status = response.status();
223
224 if !status.is_success() {
226 let raw_text = response.text().await?;
227 if let Ok(api_response) =
228 serde_json::from_str::<crate::ApiResponse<serde_json::Value>>(&raw_text)
229 && api_response.code != 0
230 {
231 return Err(Error::Api {
232 code: api_response.code,
233 message: api_response.msg,
234 });
235 }
236 return Err(Error::Api {
237 code: status.as_u16() as i32,
238 message: raw_text.trim().to_string(),
239 });
240 }
241
242 let raw_text = response.text().await?;
243
244 match serde_json::from_str::<T>(&raw_text) {
245 Ok(json) => {
246 debug!("Response status: {}, JSON: {:?}", status, json);
247 Ok(json)
248 }
249 Err(e) => {
250 debug!("JSON parse error: {}, raw response: {}", e, raw_text);
251 Err(Error::Json(e))
252 }
253 }
254 }
255
256 pub async fn delete<T>(&self, endpoint: &str) -> Result<T, Error>
258 where
259 T: serde::de::DeserializeOwned + std::fmt::Debug,
260 {
261 let url = self.get_url(endpoint);
262 let mut request = self.http_client.delete(&url);
263
264 if let Some(token) = &self.token {
265 request = request.bearer_auth(token);
266 }
267 debug!("DELETE URL: {}", url);
268
269 let response = request.send().await?;
270 let status = response.status();
271
272 if !status.is_success() {
274 let raw_text = response.text().await?;
275 if let Ok(api_response) =
276 serde_json::from_str::<crate::ApiResponse<serde_json::Value>>(&raw_text)
277 && api_response.code != 0
278 {
279 return Err(Error::Api {
280 code: api_response.code,
281 message: api_response.msg,
282 });
283 }
284 return Err(Error::Api {
285 code: status.as_u16() as i32,
286 message: raw_text.trim().to_string(),
287 });
288 }
289
290 let raw_text = response.text().await?;
291
292 match serde_json::from_str::<T>(&raw_text) {
293 Ok(json) => {
294 debug!("Response status: {}, JSON: {:?}", status, json);
295 Ok(json)
296 }
297 Err(e) => {
298 debug!("JSON parse error: {}, raw response: {}", e, raw_text);
299 Err(Error::Json(e))
300 }
301 }
302 }
303
304 pub async fn delete_with_body<T>(
306 &self,
307 endpoint: &str,
308 body: &impl Serialize,
309 ) -> Result<T, Error>
310 where
311 T: serde::de::DeserializeOwned + std::fmt::Debug,
312 {
313 let url = self.get_url(endpoint);
314 let mut request = self.http_client.delete(&url).json(body);
315
316 if let Some(token) = &self.token {
317 request = request.bearer_auth(token);
318 }
319 debug!("DELETE URL: {} with body", url);
320
321 let response = request.send().await?;
322 let status = response.status();
323
324 if !status.is_success() {
326 let raw_text = response.text().await?;
327 if let Ok(api_response) =
328 serde_json::from_str::<crate::ApiResponse<serde_json::Value>>(&raw_text)
329 && api_response.code != 0
330 {
331 return Err(Error::Api {
332 code: api_response.code,
333 message: api_response.msg,
334 });
335 }
336 return Err(Error::Api {
337 code: status.as_u16() as i32,
338 message: raw_text.trim().to_string(),
339 });
340 }
341
342 let raw_text = response.text().await?;
343
344 match serde_json::from_str::<T>(&raw_text) {
345 Ok(json) => {
346 debug!("Response status: {}, JSON: {:?}", status, json);
347 Ok(json)
348 }
349 Err(e) => {
350 debug!("JSON parse error: {}, raw response: {}", e, raw_text);
351 Err(Error::Json(e))
352 }
353 }
354 }
355}