app_forge_kit_http_client/
provider.rs1use 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}