Skip to content

Commit 5fd3d5b

Browse files
authored
Re-enable NO_PROXY envs on Windows (#2601)
In #2559, the behavior of no proxy handling on windows was changed to effectively only read from the current user's `Internet Settings` in the registry on Windows. This meant that NO_PROXY env vars were no longer respected on Windows. This commit changes that behavior and at least brings it in line with dotnet and nuget behavior (two microsoft projects) of first checking env vars and only if they are not set, check the registry settings. This fix changes the behavior of `NoProxy::from_env` if `NO_PROXY` or `no_proxy` is set to an empty string. Previously, it would have returned `None`, which is not what the documentation says should happen. It now returns an `Some(NoProxy::default())` which should functionally be the same thing for the purposes of not matching anything with the proxy. This change was done due to potential interaction with previous commit fixing #2599. I would expect that setting `NO_PROXY` to an empty string would also prevent reqwest from reading the registry settings. Closes #2599
1 parent e9215fd commit 5fd3d5b

File tree

1 file changed

+24
-4
lines changed

1 file changed

+24
-4
lines changed

src/proxy.rs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -286,8 +286,13 @@ impl Proxy {
286286

287287
#[cfg(target_os = "windows")]
288288
{
289-
let win_exceptions: String = get_windows_proxy_exceptions();
290-
proxy.no_proxy = NoProxy::from_string(&win_exceptions);
289+
// Only read from windows registry proxy settings if not available from an enviroment
290+
// variable. This is in line with the stated behavior of both dotnot and nuget on
291+
// windows. <https://github.com/seanmonstar/reqwest/issues/2599>
292+
if proxy.no_proxy.is_none() {
293+
let win_exceptions: String = get_windows_proxy_exceptions();
294+
proxy.no_proxy = NoProxy::from_string(&win_exceptions);
295+
}
291296
}
292297

293298
proxy
@@ -451,9 +456,12 @@ impl NoProxy {
451456
pub fn from_env() -> Option<NoProxy> {
452457
let raw = env::var("NO_PROXY")
453458
.or_else(|_| env::var("no_proxy"))
454-
.unwrap_or_default();
459+
.ok()?;
455460

456-
Self::from_string(&raw)
461+
// Per the docs, this returns `None` if no environment variable is set. We can only reach
462+
// here if an env var is set, so we return `Some(NoProxy::default)` if `from_string`
463+
// returns None, which occurs with an empty string.
464+
Some(Self::from_string(&raw).unwrap_or_default())
457465
}
458466

459467
/// Returns a new no-proxy configuration based on a `no_proxy` string (or `None` if no variables
@@ -1628,6 +1636,18 @@ mod tests {
16281636
// everything should go through proxy, "effectively" nothing is in no_proxy
16291637
assert_eq!(intercepted_uri(&p, "http://hyper.rs"), target);
16301638

1639+
// Also test the behavior of `NO_PROXY` being an empty string.
1640+
env::set_var("NO_PROXY", "");
1641+
1642+
// Manually construct this so we aren't use the cache
1643+
let mut p = Proxy::new(Intercept::System(Arc::new(get_sys_proxies(None))));
1644+
p.no_proxy = NoProxy::from_env();
1645+
// In the case of an empty string `NoProxy::from_env()` should return `Some(..)`
1646+
assert!(p.no_proxy.is_some());
1647+
1648+
// everything should go through proxy, "effectively" nothing is in no_proxy
1649+
assert_eq!(intercepted_uri(&p, "http://hyper.rs"), target);
1650+
16311651
// reset user setting when guards drop
16321652
drop(_g1);
16331653
drop(_g2);

0 commit comments

Comments
 (0)