/// <summary> /// Gets the proxy URIs. /// </summary> public MultiProxy GetMultiProxy(Uri uri) { // We need WinHTTP to detect and/or process a PAC (JavaScript) file. This maps to // "Automatically detect settings" and/or "Use automatic configuration script" from IE // settings. But, calling into WinHTTP can be slow especially when it has to call into // the out-of-process service to discover, load, and run the PAC file. So, we skip // calling into WinHTTP if there was a recent failure to detect a PAC file on the network. // This is a common error. The default IE settings on a Windows machine consist of the // single checkbox for "Automatically detect settings" turned on and most networks // won't actually discover a PAC file on the network since WPAD protocol isn't configured. if (_proxyHelper.AutoSettingsUsed && !_proxyHelper.RecentAutoDetectionFailure) { Interop.WinHttp.WINHTTP_PROXY_INFO proxyInfo = default; try { if (_proxyHelper.GetProxyForUrl(_sessionHandle, uri, out proxyInfo)) { // If WinHTTP just specified a Proxy with no ProxyBypass list, then // we can return the Proxy uri directly. if (proxyInfo.ProxyBypass == IntPtr.Zero) { if (proxyInfo.Proxy != IntPtr.Zero) { string proxyStr = Marshal.PtrToStringUni(proxyInfo.Proxy) !; return(MultiProxy.CreateLazy(_failedProxies, proxyStr, IsSecureUri(uri))); } else { return(MultiProxy.Empty); } } // A bypass list was also specified. This means that WinHTTP has fallen back to // using the manual IE settings specified and there is a ProxyBypass list also. // Since we're not really using the full WinHTTP stack, we need to use HttpSystemProxy // to do the computation of the final proxy uri merging the information from the Proxy // and ProxyBypass strings. } else { return(MultiProxy.Empty); } } finally { Marshal.FreeHGlobal(proxyInfo.Proxy); Marshal.FreeHGlobal(proxyInfo.ProxyBypass); } } // Fallback to manual settings if present. if (_proxyHelper.ManualSettingsUsed) { if (_bypassLocal) { IPAddress?address; if (uri.IsLoopback) { // This is optimization for loopback addresses. // Unfortunately this does not work for all local addresses. return(MultiProxy.Empty); } // Pre-Check if host may be IP address to avoid parsing. if (uri.HostNameType == UriHostNameType.IPv6 || uri.HostNameType == UriHostNameType.IPv4) { // RFC1123 allows labels to start with number. // Leading number may or may not be IP address. // IPv6 [::1] notation. '[' is not valid character in names. if (IPAddress.TryParse(uri.IdnHost, out address)) { // Host is valid IP address. // Check if it belongs to local system. foreach (IPAddress a in _localIp !) { if (a.Equals(address)) { return(MultiProxy.Empty); } } } } if (uri.HostNameType != UriHostNameType.IPv6 && !uri.IdnHost.Contains('.')) { // Not address and does not have a dot. // Hosts without FQDN are considered local. return(MultiProxy.Empty); } } // Check if we have other rules for bypass. if (_bypass != null) { foreach (string entry in _bypass) { // IdnHost does not have []. if (SimpleRegex.IsMatchWithStarWildcard(uri.IdnHost, entry)) { return(MultiProxy.Empty); } } } // We did not find match on bypass list. return(IsSecureUri(uri) ? _secureProxy : _insecureProxy); } return(MultiProxy.Empty); }
public void InputMatchesStarWildcardPattern(string input, string pattern, bool expected) { Assert.Equal(expected, SimpleRegex.IsMatchWithStarWildcard(input, pattern)); }