1use crate::constants::env::system;
5use std::sync::{Mutex, OnceLock};
6
7static PROXY_CACHE: OnceLock<Mutex<ProxyConfig>> = OnceLock::new();
8
9#[derive(Debug, Clone, Default)]
11pub struct ProxyConfig {
12 pub http_proxy: Option<String>,
13 pub https_proxy: Option<String>,
14 pub no_proxy: Option<String>,
15}
16
17pub fn get_proxy_config() -> ProxyConfig {
19 PROXY_CACHE
20 .get_or_init(|| Mutex::new(load_proxy_config()))
21 .lock()
22 .unwrap()
23 .clone()
24}
25
26fn load_proxy_config() -> ProxyConfig {
27 let http_proxy = std::env::var(system::HTTP_PROXY)
28 .or_else(|_| std::env::var(system::HTTP_PROXY_LOWER))
29 .ok();
30
31 let https_proxy = std::env::var(system::HTTPS_PROXY)
32 .or_else(|_| std::env::var(system::HTTPS_PROXY_LOWER))
33 .ok();
34
35 let no_proxy = std::env::var(system::NO_PROXY)
36 .or_else(|_| std::env::var(system::NO_PROXY_LOWER))
37 .ok();
38
39 ProxyConfig {
40 http_proxy,
41 https_proxy,
42 no_proxy,
43 }
44}
45
46pub fn clear_proxy_cache() {
48 }
50
51pub fn get_http_proxy() -> Option<String> {
53 get_proxy_config().http_proxy.clone()
54}
55
56pub fn get_https_proxy() -> Option<String> {
58 get_proxy_config().https_proxy.clone()
59}
60
61pub fn get_no_proxy() -> Option<String> {
63 get_proxy_config().no_proxy.clone()
64}
65
66pub fn should_bypass_proxy(host: &str) -> bool {
68 let no_proxy = match get_no_proxy() {
69 Some(np) => np,
70 None => return false,
71 };
72
73 for pattern in no_proxy.split(',') {
75 let pattern = pattern.trim();
76
77 if pattern.is_empty() {
78 continue;
79 }
80
81 if pattern.starts_with('.') {
82 let domain = &pattern[1..];
84 if host.ends_with(domain) || host == domain {
85 return true;
86 }
87 } else if host == pattern {
88 return true;
89 }
90 }
91
92 false
93}
94
95pub fn configure_global_agents() {
97 clear_proxy_cache();
99}