wapm_cli/
proxy.rs

1//! Code for dealing with setting things up to proxy network requests
2use 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
16/// Tries to set up a proxy
17///
18/// This function reads from wapm config's `proxy.url` first, then checks
19/// `ALL_PROXY`, `HTTPS_PROXY`, and `HTTP_PROXY` environment variables, in both
20/// upper case and lower case, in that order.
21///
22/// If a proxy is specified in wapm config's `proxy.url`, it is assumed
23/// to be a general proxy
24///
25/// A return value of `Ok(None)` means that there was no attempt to set up a proxy,
26/// `Ok(Some(proxy))` means that the proxy was set up successfully, and `Err(e)` that
27/// there was a failure while attempting to set up the proxy.
28pub 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}