1use thiserror::Error;
3
4#[derive(Debug, Error)]
5pub enum ProxyError {
6 #[error("Failed to parse URL from {}: {}", url_location, error_message)]
7 UrlParseError {
8 url_location: String,
9 error_message: String,
10 },
11
12 #[error("Could not connect to proxy: {0}")]
13 ConnectionError(String),
14}
15
16pub fn maybe_set_up_proxy() -> anyhow::Result<Option<reqwest::Proxy>> {
29 use std::env;
30 let maybe_proxy_url = crate::config::Config::from_file()
31 .ok()
32 .and_then(|config| config.proxy.url);
33 let proxy = if let Some(proxy_url) = maybe_proxy_url {
34 reqwest::Proxy::all(&proxy_url).map(|proxy| (proxy_url, proxy, "`proxy.url` config key"))
35 } else if let Ok(proxy_url) = env::var("ALL_PROXY").or_else(|_| env::var("all_proxy")) {
36 reqwest::Proxy::all(&proxy_url).map(|proxy| (proxy_url, proxy, "ALL_PROXY"))
37 } else if let Ok(https_proxy_url) = env::var("HTTPS_PROXY").or_else(|_| env::var("https_proxy"))
38 {
39 reqwest::Proxy::https(&https_proxy_url).map(|proxy| (https_proxy_url, proxy, "HTTPS_PROXY"))
40 } else if let Ok(http_proxy_url) = env::var("HTTP_PROXY").or_else(|_| env::var("http_proxy")) {
41 reqwest::Proxy::http(&http_proxy_url).map(|proxy| (http_proxy_url, proxy, "http_proxy"))
42 } else {
43 return Ok(None);
44 }
45 .map_err(|e| ProxyError::ConnectionError(e.to_string()))
46 .and_then(
47 |(proxy_url_str, proxy, url_location): (String, _, &'static str)| {
48 url::Url::parse(&proxy_url_str)
49 .map_err(|e| ProxyError::UrlParseError {
50 url_location: url_location.to_string(),
51 error_message: e.to_string(),
52 })
53 .map(|url| {
54 if !(url.username().is_empty()) && url.password().is_some() {
55 proxy.basic_auth(url.username(), url.password().unwrap_or_default())
56 } else {
57 proxy
58 }
59 })
60 },
61 )?;
62
63 Ok(Some(proxy))
64}