url_cleaner_engine/glue/
http_client_config.rs1use std::collections::HashSet;
4
5use serde::{Serialize, Deserialize};
6#[cfg(feature = "http")]
7use reqwest::header::HeaderMap;
8
9#[expect(unused_imports, reason = "Used in docs.")]
10use crate::types::*;
11use crate::glue::*;
12use crate::util::*;
13
14#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, Suitability)]
16#[serde(deny_unknown_fields)]
17pub struct HttpClientConfig {
18 #[serde(default, skip_serializing_if = "is_default", with = "serde_headermap")]
20 pub default_headers: HeaderMap,
21 #[serde(default, skip_serializing_if = "is_default")]
25 pub redirect_policy: RedirectPolicy,
26 #[serde(default, skip_serializing_if = "is_default")]
30 pub https_only: bool,
31 #[serde(default, skip_serializing_if = "is_default")]
35 pub referer: bool,
36 #[serde(default, skip_serializing_if = "is_default")]
40 pub proxies: Vec<ProxyConfig>,
41 #[serde(default, skip_serializing_if = "is_default")]
45 pub no_proxy: bool,
46 #[serde(default, skip_serializing_if = "is_default")]
52 pub extra_root_certificates: HashSet<String>
53}
54
55#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Suitability)]
63#[serde(deny_unknown_fields)]
64pub enum RedirectPolicy {
65 Limited(usize),
69 None
71}
72
73impl Default for RedirectPolicy {
74 fn default() -> Self {
76 Self::Limited(10)
77 }
78}
79
80impl From<RedirectPolicy> for reqwest::redirect::Policy {
81 fn from(value: RedirectPolicy) -> Self {
82 match value {
83 RedirectPolicy::Limited(x) => Self::limited(x),
84 RedirectPolicy::None => Self::none()
85 }
86 }
87}
88
89impl HttpClientConfig {
90 pub fn make(&self) -> reqwest::Result<reqwest::blocking::Client> {
96 let mut temp = reqwest::blocking::Client::builder().default_headers(self.default_headers.clone())
97 .redirect(self.redirect_policy.clone().into())
98 .https_only(self.https_only)
99 .referer(self.referer);
100 for proxy in &self.proxies {
101 temp = temp.proxy(proxy.clone().make()?);
102 }
103 if self.no_proxy {temp = temp.no_proxy();}
104 for cert in &self.extra_root_certificates {
105 temp = temp.add_root_certificate(reqwest::tls::Certificate::from_pem(cert.as_bytes())?);
106 }
107 temp.build()
108 }
109}
110
111#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize, Suitability)]
113#[serde(deny_unknown_fields)]
114pub struct HttpClientConfigDiff {
115 #[serde(default, skip_serializing_if = "is_default")]
117 pub redirect_policy: Option<RedirectPolicy>,
118 #[serde(default, skip_serializing_if = "is_default", with = "serde_headermap")]
120 pub add_default_headers: HeaderMap,
121 #[serde(default, skip_serializing_if = "is_default")]
123 pub https_only: Option<bool>,
124 #[serde(default, skip_serializing_if = "is_default")]
126 pub set_proxies: Option<Vec<ProxyConfig>>,
127 #[serde(default, skip_serializing_if = "is_default")]
129 pub add_proxies: Vec<ProxyConfig>,
130 #[serde(default, skip_serializing_if = "is_default")]
132 pub no_proxy: Option<bool>,
133 #[serde(default, skip_serializing_if = "is_default")]
135 pub referer: Option<bool>,
136 #[serde(default, skip_serializing_if = "is_default")]
138 pub add_extra_root_certificates: HashSet<String>,
139 #[serde(default, skip_serializing_if = "is_default")]
141 pub remove_extra_root_certificates: HashSet<String>
142}
143
144impl HttpClientConfigDiff {
145 pub fn apply_once(self, to: &mut HttpClientConfig) {
149 debug!(HttpClientConfigDiff::apply_once, &self, to);
150 if let Some(new_redirect_policy) = self.redirect_policy {to.redirect_policy = new_redirect_policy;}
151 to.default_headers.extend(self.add_default_headers);
152 if let Some(https_only) = self.https_only {to.https_only = https_only;}
153 if let Some(set_proxies) = self.set_proxies {to.proxies = set_proxies;}
154 to.proxies.extend(self.add_proxies);
155 if let Some(no_proxy) = self.no_proxy {to.no_proxy = no_proxy;}
156 if let Some(referer) = self.referer {to.no_proxy = referer;}
157 to.extra_root_certificates.extend(self.add_extra_root_certificates);
158 to.extra_root_certificates.retain(|extra_root_certificate| !self.remove_extra_root_certificates.contains(extra_root_certificate));
159 }
160
161 pub fn apply_multiple(&self, to: &mut HttpClientConfig) {
165 debug!(HttpClientConfigDiff::apply_multiple, self, to);
166 if let Some(new_redirect_policy) = &self.redirect_policy {to.redirect_policy = new_redirect_policy.clone();}
167 to.default_headers.extend(self.add_default_headers.clone());
168 if let Some(https_only) = self.https_only {to.https_only = https_only;}
169 if let Some(set_proxies) = &self.set_proxies {to.proxies.clone_from(set_proxies);}
170 to.proxies.extend(self.add_proxies.clone());
171 if let Some(no_proxy) = self.no_proxy {to.no_proxy = no_proxy;}
172 if let Some(referer) = self.referer {to.no_proxy = referer;}
173 to.extra_root_certificates.extend(self.add_extra_root_certificates.clone());
174 to.extra_root_certificates.retain(|extra_root_certificate| !self.remove_extra_root_certificates.contains(extra_root_certificate));
175 }
176}