weer_api/api/
base_api.rs

1use url::Url;
2use ureq::Error;
3use serde::{Serialize, Deserialize};
4use std::{time::Duration, thread};
5
6use crate::Client;
7
8pub trait BaseApi<'a> 
9where
10    Self::Model: Serialize + for<'de> Deserialize<'de>
11{
12    type Model;
13
14    fn path(&self) -> &str;
15    fn params(&self) -> Vec<(&str, String)>;
16    fn client(&self) -> &'a Client;
17
18    fn call(&self) -> Result<Self::Model, ureq::Error> {
19        let client = self.client();
20        let url = Url::parse_with_params(
21            format!(
22                "http{}://api.weatherapi.com/v1/{}.json", 
23                if client.https { "s" } else { "" }, 
24                self.path()
25            ).as_str(), 
26            &self.params()
27        )?;
28        
29        for _ in 1..2 {
30            match client.agent.request_url("GET", &url).call() {
31                Err(Error::Status(503, r)) | Err(Error::Status(429, r)) => {
32                    let retry: Option<u64> = r.header("retry-after")
33                        .and_then(|h| h.parse().ok());
34                    let retry = retry.unwrap_or(5);
35                    thread::sleep(Duration::from_secs(retry));
36                }
37                result => return Ok(result?.into_json()?),
38            };
39        }
40
41        // Ran out of retries; try one last time and return whatever result we get.
42        Ok(client.agent.request_url("GET", &url).call()?.into_json()?)
43    }
44}