1use std::collections::{BTreeMap, HashMap};
2use std::fmt::Debug;
3
4use reqwest::Response;
5
6use crate::Result;
7
8pub(crate) type Params = BTreeMap<String, Option<String>>;
9pub(crate) type Headers = HashMap<String, String>;
10
11pub(crate) struct Request {
12    pub(crate) url: String,
13    pub(crate) method: reqwest::Method,
14    pub(crate) headers: Headers,
15    pub(crate) params: Params,
16    pub(crate) body: Vec<u8>,
17}
18
19impl Request {
20    pub(crate) async fn send(self, client: &reqwest::Client) -> Result<Response> {
21        let Self {
22            url,
23            method,
24            headers,
25            params,
26            body,
27        } = self;
28
29        let mut req = client.request(method, url);
30        for (k, v) in headers {
31            req = req.header(&k, &v);
32        }
33
34        if !body.is_empty() {
35            req = req.body(body);
36        }
37
38        Ok(req.send().await?)
39    }
40}
41
42pub(crate) trait Credentials: Send + Sync {
43    fn access_key_id(&self) -> &str;
44    fn access_key_secret(&self) -> &str;
45    fn security_token(&self) -> &str;
46}
47
48impl Debug for dyn Credentials {
49    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50        f.debug_struct("Credentials")
51            .field("access_key_id", &self.access_key_id().to_string())
52            .field("access_key_secret", &self.access_key_secret().to_string())
53            .field("security_token", &self.security_token().to_string())
54            .finish()
55    }
56}