Skip to main content

proxy_override

Function proxy_override 

Source
pub fn proxy_override(spec: &str) -> BypassRules
Expand description

Parse a Windows ProxyOverride registry value into BypassRules.

Like no_proxy, but entries are separated by ;, , or whitespace, as WinHTTP documents, and a bare name matches that name alone rather than the domain under it: contoso.com here does not bypass api.contoso.com. Write *.contoso.com for the subdomains, which is also what Windows asks for; .contoso.com is rejected rather than read, because no measured reader grants it. So is contoso.com.: the store compares a trailing . as written, so it would match only a destination spelled with one. A CIDR entry is rejected too, because Windows answers a / with the whole list: write the range as the wildcard Windows does read, 10.*. <local> → HostPattern::Local and <-loopback> (IE9+) → HostPattern::SubtractImplicit are read by no_proxy as well as by this one, as Chromium reads them. Malformed entries skipped into BypassRules::rejected.

An IPv4 address entry is read only as four decimal octets. WinINet and WinHTTP compare an address entry with the destination as text, so 012.1.2.3 there is not 10.1.2.3 in either position; such an entry is rejected, where no_proxy reads it as the address a URL parser would. Limitation: every entry point reads the destination folded (a Url or a Host already holds 012.1.2.3 as 10.1.2.3, and matches_authority parses its text the same way), so an entry 10.1.2.3 or 10.* reports a bypass for a destination written 012.1.2.3, which Windows hands to the proxy.

The bare-name rule is measured against WinINet and WinHTTP. The reimplementations this crate reads alongside, Chromium and libproxy, answer the question differently, so neither could settle it. The readings are the rows of a_bare_name_in_a_windows_list_is_the_one_host in tests/bypass.rs.

The implicit set is measured the same way, and is ImplicitBypass::WinInet: localhost, loopback, 127.0.0.1, ::1 and the link-local ranges. It excludes the rest of 127.0.0.0/8, *.localhost and IPv4-mapped spellings. WinHTTP agrees on the link-local ranges and bypasses all of 127.0.0.0/8 even under <-loopback>. The store is WinINet’s, so this follows WinINet, and a WinHTTP client is therefore told “proxy” for loopback it sends direct. The rows are wininet_implicit_bypass_is_the_measured_six in tests/bypass.rs.

let rules = parse::proxy_override("<local>;*.contoso.com;<-loopback>");
assert!(rules.excludes_simple_hostnames());
assert!(!rules.bypass_loopback());
assert!(rules.matches_authority("www.contoso.com"));

// Whitespace separates too, so this is two rules and not one dead one.
let rules = parse::proxy_override("*.contoso.com intranet");
assert!(rules.matches_authority("www.contoso.com"));
assert!(rules.matches_authority("intranet"));

// A bare name is the host itself. The same text in `no_proxy` takes the subdomains.
let rules = parse::proxy_override("contoso.com");
assert!(rules.matches_authority("contoso.com"));
assert!(!rules.matches_authority("api.contoso.com"));
assert!(parse::no_proxy("contoso.com").matches_authority("api.contoso.com"));

// A `/` is recorded, not read. `no_proxy` takes the same text as a mask.
let rules = parse::proxy_override("10.0.0.0/8");
assert!(!rules.matches_authority("10.1.2.3"));
assert_eq!(rules.rejected.len(), 1);
assert!(parse::no_proxy("10.0.0.0/8").matches_authority("10.1.2.3"));