firefly_iii_rust/
client.rs1use crate::requests::*;
2use crate::response::*;
3use crate::error::Result;
4use crate::error::Error;
5use crate::http::Method;
6use serde::de::DeserializeOwned;
7
8#[derive(Debug)]
13pub struct Client {
14 base_url: String,
15 token: String,
16 client: ureq::Agent,
17}
18
19pub fn new(base_url: &str, token: &str) -> Client {
20 let client = ureq::Agent::new();
21 Client{base_url: base_url.into(), token: token.into(), client}
22}
23
24impl Client {
25 pub fn call<R: Request>(&self, request: R) -> Result<R::Response> {
33 let url = format!("{}{}", self.base_url, request.endpoint());
34 let mut req = match R::METHOD {
35 Method::Head => self.client.head(&url),
36 Method::Get => self.client.get(&url),
37 Method::Post => self.client.post(&url),
38 Method::Put => self.client.put(&url),
39 Method::Delete => self.client.delete(&url),
40 };
41
42 req = req.set("Authorization", &format!("Bearer {}", self.token));
43 req = req.set("accept", "application/vnd.api+json");
44 req = req.set("Content-Type", "application/json");
45
46 for (k, v) in request.headers().iter() {
47 req = req.set(k,v);
48 }
49
50 let resp = match request.body() {
51 Some(body) => {
52 req.send_json(body)
53 },
54 None => req.call(),
55 };
56
57 match resp {
58 Ok(resp) => {
59 if resp.status() == 204 {
60 Ok(R::Response::default())
61 } else {
62 let result: R::Response = resp.into_json()
63 .expect("json conversion failed on us");
64 Ok(result)
65 }
66 },
67 Err(err) => {
68 if let Some(body) = request.body() {
69 eprintln!("Body: {:#?}", body);
70 }
71 match err {
72 ureq::Error::Status(status, response) => {
73 let response_msg = response.into_string().unwrap_or_else(|_| "failed to parse response".to_string());
74 Err(Error::HTTPErr{status, response_msg: response_msg.to_string()})
75 },
76 _ => Err(Error::IOErr(err.to_string())),
77 }
78 },
79 }
80 }
81
82 pub fn fetch_all<R, T>(&self, mut request: R) -> Result<Vec<T>>
85 where
86 R: Request<Response = PaginatedResponse<Vec<T>>> + Paginated + Clone,
87 T: DeserializeOwned,
88 {
89 let mut current_page = 1;
90 let mut all_items = Vec::new();
91
92 loop {
93 request.set_page(current_page);
94 let response = self.call(request.clone())?;
95 all_items.extend(response.data.into_iter());
96
97 if request.get_page() < request.max_page() {
98 current_page += 1;
99 } else {
100 break; }
102 }
103
104 Ok(all_items)
105 }
106}
107