pub fn detect() -> Option<String> {
#[cfg(target_os = "macos")]
if let Some(p) = macos_scutil_proxy() {
return Some(p);
}
env_proxy()
}
fn env_proxy() -> Option<String> {
for key in [
"ALL_PROXY",
"all_proxy",
"HTTPS_PROXY",
"https_proxy",
"HTTP_PROXY",
"http_proxy",
] {
if let Some(v) = std::env::var(key).ok().filter(|v| !v.is_empty()) {
return Some(v);
}
}
None
}
#[cfg(target_os = "macos")]
fn macos_scutil_proxy() -> Option<String> {
use std::process::Command;
let out = Command::new("scutil").arg("--proxy").output().ok()?;
let text = String::from_utf8_lossy(&out.stdout);
let val = |key: &str| -> Option<String> {
for line in text.lines() {
let line = line.trim();
if let Some(rest) = line.strip_prefix(key) {
let rest = rest.trim_start();
if let Some(rest) = rest.strip_prefix(':') {
return Some(rest.trim().to_string());
}
}
}
None
};
let enabled = |key: &str| val(key).as_deref() == Some("1");
if let (true, Some(h), Some(p)) = (enabled("SOCKSEnable"), val("SOCKSProxy"), val("SOCKSPort"))
{
return Some(format!("socks5h://{h}:{p}"));
}
for prefix in ["HTTPS", "HTTP"] {
if let (true, Some(h), Some(p)) = (
enabled(&format!("{prefix}Enable")),
val(&format!("{prefix}Proxy")),
val(&format!("{prefix}Port")),
) {
return Some(format!("http://{h}:{p}"));
}
}
None
}