Skip to main content

app_forge_kit_http_client/
provider.rs

1use crate::{Error, RequestBuilderProvider, config, types};
2use http::{HeaderMap, HeaderName, HeaderValue, header};
3use std::collections::HashMap;
4use std::str::FromStr;
5use url::Url;
6
7#[derive(Clone)]
8pub struct Provider {
9    client: reqwest::Client,
10    destination: Option<Url>,
11    auth: Option<config::Auth>,
12    headers: Option<HashMap<String, String>>,
13}
14
15impl Provider {
16    fn compose_headers(headers_hash_map: &HashMap<String, String>) -> HeaderMap {
17        let mut headers = HeaderMap::with_capacity(headers_hash_map.len());
18
19        for (key, value) in headers_hash_map {
20            if let (Ok(name), Ok(h_value)) =
21                (HeaderName::from_str(key), HeaderValue::from_str(value))
22            {
23                headers.insert(name, h_value);
24            }
25        }
26
27        headers
28    }
29    fn client_builder_proxy_config(
30        client_builder: reqwest::ClientBuilder,
31        config: &config::Config,
32    ) -> Result<reqwest::ClientBuilder, Error> {
33        if let Some(config_proxy) = &config.proxy {
34            let mut client_proxy = match config_proxy.destination.scheme() {
35                "http" => reqwest::Proxy::http(config_proxy.destination.as_str()),
36                "https" => reqwest::Proxy::https(config_proxy.destination.as_str()),
37                _ => reqwest::Proxy::all(config_proxy.destination.as_str()),
38            }?;
39
40            if let Some(auth) = &config_proxy.auth {
41                match auth {
42                    config::Auth::Basic(auth_basic) => {
43                        client_proxy = client_proxy.basic_auth(
44                            auth_basic.clone().username.as_str(),
45                            auth_basic.clone().password.unwrap_or_default().as_str(),
46                        )
47                    }
48                    config::Auth::Bearer(auth_bearer) => {
49                        client_proxy = client_proxy.custom_http_auth(HeaderValue::from_str(
50                            format!("Bearer {}", auth_bearer).as_str(),
51                        )?)
52                    }
53                    config::Auth::Header(auth_header) => {
54                        let header_map = Self::compose_headers(auth_header);
55
56                        if let Some(value) = header_map.get(header::PROXY_AUTHORIZATION) {
57                            client_proxy = client_proxy.custom_http_auth(value.clone());
58                        }
59                    }
60                };
61            }
62
63            return Ok(client_builder.proxy(client_proxy));
64        }
65
66        Ok(client_builder)
67    }
68
69    pub fn new(config: &config::Config) -> Result<Self, Error> {
70        let mut client_builder = reqwest::ClientBuilder::new();
71
72        client_builder = Self::client_builder_proxy_config(client_builder, config)?;
73
74        Ok(Self {
75            client: client_builder.build()?,
76            destination: config.destination.clone(),
77            auth: config.auth.clone(),
78            headers: config.headers.clone(),
79        })
80    }
81
82    fn compose_request_url(&self, uri: &types::Uri) -> Result<Url, Error> {
83        if let Some(destination) = &self.destination {
84            let mut base_url = destination.clone();
85
86            let mut base_url_path = base_url.path();
87            base_url_path = base_url_path.strip_suffix("/").unwrap_or(base_url_path);
88
89            let mut uri_path = uri.path();
90            uri_path = uri_path.strip_prefix("/").unwrap_or(uri_path);
91
92            let url_path = [base_url_path, uri_path].join("/");
93
94            base_url.set_path(url_path.as_str());
95            base_url.set_query(uri.query());
96
97            return Ok(base_url);
98        }
99
100        let url = Url::parse(uri.to_string().as_str())?;
101
102        Ok(url)
103    }
104}
105
106impl RequestBuilderProvider for Provider {
107    fn request(
108        &self,
109        method: types::Method,
110        uri: &types::Uri,
111    ) -> Result<types::RequestBuilder, Error> {
112        let request_url = self.compose_request_url(uri)?;
113
114        let mut request_builder = self.client.request(method, request_url);
115
116        if let Some(auth) = &self.auth {
117            match auth {
118                config::Auth::Basic(auth_basic) => {
119                    request_builder = request_builder
120                        .basic_auth(auth_basic.username.clone(), auth_basic.password.clone())
121                }
122                config::Auth::Bearer(auth_bearer) => {
123                    request_builder = request_builder.bearer_auth(auth_bearer.clone())
124                }
125                config::Auth::Header(auth_header) => {
126                    request_builder = request_builder.headers(Self::compose_headers(auth_header))
127                }
128            }
129        }
130
131        if let Some(headers) = &self.headers {
132            request_builder = request_builder.headers(Self::compose_headers(headers))
133        }
134
135        Ok(request_builder)
136    }
137}