< Summary

Line coverage
0%
Covered lines: 0
Uncovered lines: 185
Coverable lines: 185
Total lines: 391
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 88
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
File 1: .ctor(...)0%10100%
File 1: GetUriFromString(...)0%40400%
File 1: IsMatchInBypassList(...)0%20200%
File 1: GetProxy(...)0%220%
File 1: IsBypassed(...)0%220%
File 2: TryCreate(...)0%14140%

File(s)

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpEnvironmentProxy.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System.Collections.Generic;
 5
 6namespace System.Net.Http
 7{
 8    internal sealed class HttpEnvironmentProxyCredentials : ICredentials
 9    {
 10        // Wrapper class for cases when http and https has different authentication.
 11        private readonly NetworkCredential? _httpCred;
 12        private readonly NetworkCredential? _httpsCred;
 13        private readonly Uri? _httpProxy;
 14        private readonly Uri? _httpsProxy;
 15
 16        public HttpEnvironmentProxyCredentials(Uri? httpProxy, NetworkCredential? httpCred,
 17                                                Uri? httpsProxy, NetworkCredential? httpsCred)
 18        {
 19            _httpCred = httpCred;
 20            _httpsCred = httpsCred;
 21            _httpProxy = httpProxy;
 22            _httpsProxy = httpsProxy;
 23        }
 24
 25        public NetworkCredential? GetCredential(Uri? uri, string authType)
 26        {
 27            if (uri == null)
 28            {
 29                return null;
 30            }
 31            return uri.Equals(_httpProxy) ? _httpCred :
 32                   uri.Equals(_httpsProxy) ? _httpsCred : null;
 33        }
 34
 35        public static HttpEnvironmentProxyCredentials? TryCreate(Uri? httpProxy, Uri? httpsProxy)
 36        {
 37            NetworkCredential? httpCred = null;
 38            NetworkCredential? httpsCred = null;
 39
 40            if (httpProxy != null)
 41            {
 42                httpCred = GetCredentialsFromString(httpProxy.UserInfo);
 43            }
 44            if (httpsProxy != null)
 45            {
 46                httpsCred = GetCredentialsFromString(httpsProxy.UserInfo);
 47            }
 48            if (httpCred == null && httpsCred == null)
 49            {
 50                return null;
 51            }
 52            return new HttpEnvironmentProxyCredentials(httpProxy, httpCred, httpsProxy, httpsCred);
 53        }
 54
 55        /// <summary>
 56        /// Converts string containing user:password to NetworkCredential object
 57        /// </summary>
 58        private static NetworkCredential? GetCredentialsFromString(string? value)
 59        {
 60            if (string.IsNullOrWhiteSpace(value))
 61            {
 62                return null;
 63            }
 64
 65            if (value == ":")
 66            {
 67                return CredentialCache.DefaultNetworkCredentials;
 68            }
 69
 70            value = Uri.UnescapeDataString(value);
 71
 72            string password = "";
 73            string? domain = null;
 74            int idx = value.IndexOf(':');
 75            if (idx != -1)
 76            {
 77                password = value.Substring(idx + 1);
 78                value = value.Substring(0, idx);
 79            }
 80
 81            idx = value.IndexOf('\\');
 82            if (idx != -1)
 83            {
 84                domain = value.Substring(0, idx);
 85                value = value.Substring(idx + 1);
 86            }
 87
 88            return new NetworkCredential(value, password, domain);
 89        }
 90    }
 91
 92    internal sealed partial class HttpEnvironmentProxy : IWebProxy
 93    {
 94        private const string EnvAllProxyUC = "ALL_PROXY";
 95        private const string EnvHttpProxyUC = "HTTP_PROXY";
 96        private const string EnvHttpsProxyUC = "HTTPS_PROXY";
 97        private const string EnvNoProxyUC = "NO_PROXY";
 98        private const string EnvCGI = "GATEWAY_INTERFACE"; // Running in a CGI environment.
 99
 100        private readonly Uri? _httpProxyUri;                  // String URI for HTTP requests
 101        private readonly Uri? _httpsProxyUri;                 // String URI for HTTPS requests
 102        private readonly List<string>? _bypass;               // list of domains or IP addresses not to proxy
 103        private readonly List<IPNetwork>? _bypassNetworks;    // list of subnet ranges not to proxy
 104        private ICredentials? _credentials;
 105
 0106        private HttpEnvironmentProxy(Uri? httpProxy, Uri? httpsProxy, string? bypassList)
 0107        {
 0108            _httpProxyUri = httpProxy;
 0109            _httpsProxyUri = httpsProxy;
 110
 0111            _credentials = HttpEnvironmentProxyCredentials.TryCreate(httpProxy, httpsProxy);
 112
 0113            if (bypassList != null)
 0114            {
 0115                foreach (string entry in bypassList.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOption
 0116                {
 0117                    if (IPNetwork.TryParse(entry, out IPNetwork networkEntry))
 0118                    {
 0119                        _bypassNetworks ??= new List<IPNetwork>();
 0120                        _bypassNetworks.Add(networkEntry);
 0121                    }
 122                    else
 0123                    {
 0124                        _bypass ??= new List<string>();
 0125                        _bypass.Add(entry);
 0126                    }
 0127                }
 0128            }
 0129        }
 130
 131        /// <summary>
 132        /// Attempt to parse a partial Uri string into a Uri object.
 133        /// The string may contain the scheme, user info, host, and port. The host is the only required part.
 134        /// Example expected inputs: contoso.com, contoso.com:8080, http://contoso.com/, user@contoso.com.
 135        /// </summary>
 136        /// <returns><see langword="null"/> if parsing fails.</returns>
 137        private static unsafe Uri? GetUriFromString(string? value)
 0138        {
 0139            if (string.IsNullOrEmpty(value))
 0140            {
 0141                return null;
 142            }
 143
 0144            int hostIndex = 0;
 0145            string protocol = "http";
 0146            ushort port = 80;
 147
 0148            if (value.StartsWith("http://", StringComparison.OrdinalIgnoreCase))
 0149            {
 0150                hostIndex = 7;
 0151            }
 0152            else if (value.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
 0153            {
 0154                hostIndex = 8;
 0155                protocol = "https";
 0156                port = 443;
 0157            }
 0158            else if (value.StartsWith("socks4://", StringComparison.OrdinalIgnoreCase))
 0159            {
 0160                hostIndex = 9;
 0161                protocol = "socks4";
 0162            }
 0163            else if (value.StartsWith("socks5://", StringComparison.OrdinalIgnoreCase))
 0164            {
 0165                hostIndex = 9;
 0166                protocol = "socks5";
 0167            }
 0168            else if (value.StartsWith("socks5h://", StringComparison.OrdinalIgnoreCase))
 0169            {
 0170                hostIndex = 10;
 0171                protocol = "socks5h";
 0172            }
 0173            else if (value.StartsWith("socks4a://", StringComparison.OrdinalIgnoreCase))
 0174            {
 0175                hostIndex = 10;
 0176                protocol = "socks4a";
 0177            }
 178
 0179            if (hostIndex > 0)
 0180            {
 0181                value = value.Substring(hostIndex);
 0182            }
 183
 0184            string? user = null;
 0185            string? password = null;
 186            string host;
 187
 188            // Check if there is authentication part with user and possibly password.
 189            // Curl accepts raw text and that may break URI parser.
 0190            int separatorIndex = value.LastIndexOf('@');
 0191            if (separatorIndex != -1)
 0192            {
 193                // The User and password may or may not be URL encoded.
 194                // Curl seems to accept both. To match that, we also decode the value.
 0195                string auth = Uri.UnescapeDataString(value.AsSpan(0, separatorIndex));
 196
 0197                value = value.Substring(separatorIndex + 1);
 0198                separatorIndex = auth.IndexOf(':');
 0199                if (separatorIndex == -1)
 0200                {
 0201                    user = auth;
 0202                }
 203                else
 0204                {
 0205                    user = auth.Substring(0, separatorIndex);
 0206                    password = auth.Substring(separatorIndex + 1);
 0207                }
 0208            }
 209
 210            // We expect inputs to not contain the path/query/fragment, but we do handle some simple cases like a traili
 211            // An arbitrary path can break this parsing logic, but we expect environment variables to be trusted and wel
 0212            int delimiterIndex = value.IndexOfAny('/', '?', '#');
 0213            if (delimiterIndex >= 0)
 0214            {
 0215                value = value.Substring(0, delimiterIndex);
 0216            }
 217
 0218            int ipV6AddressEnd = value.IndexOf(']');
 0219            separatorIndex = value.LastIndexOf(':');
 220            // No ':' or it is part of IPv6 address.
 0221            if (separatorIndex == -1 || (ipV6AddressEnd != -1 && separatorIndex < ipV6AddressEnd))
 0222            {
 0223                host = value;
 0224            }
 225            else
 0226            {
 0227                host = value.Substring(0, separatorIndex);
 228
 0229                if (!ushort.TryParse(value.AsSpan(separatorIndex + 1), out port))
 0230                {
 0231                    return null;
 232                }
 0233            }
 234
 235            try
 0236            {
 0237                UriBuilder ub = new UriBuilder(protocol, host, port);
 0238                if (user != null)
 0239                {
 0240                    ub.UserName = Uri.EscapeDataString(user);
 0241                }
 242
 0243                if (password != null)
 0244                {
 0245                    ub.Password = Uri.EscapeDataString(password);
 0246                }
 247
 0248                Uri uri = ub.Uri;
 249
 250                // if both user and password exist and are empty we should preserve that and use default credentials.
 251                // UriBuilder does not handle that now e.g. does not distinguish between empty and missing.
 0252                if (user == "" && password == "")
 0253                {
 0254                    Span<Range> tokens = stackalloc Range[3];
 0255                    ReadOnlySpan<char> uriSpan = uri.ToString();
 0256                    if (uriSpan.Split(tokens, '/') == 3)
 0257                    {
 0258                        uri = new Uri($"{uriSpan[tokens[0]]}//:@{uriSpan[tokens[2]]}");
 0259                    }
 0260                }
 261
 0262                return uri;
 263            }
 0264            catch { };
 0265            return null;
 0266        }
 267
 268        /// <summary>
 269        /// This function returns true if given Host match bypass list.
 270        /// Note, that the list is common for http and https.
 271        /// </summary>
 272        private bool IsMatchInBypassList(Uri input)
 0273        {
 0274            if (_bypass != null)
 0275            {
 0276                foreach (string s in _bypass)
 0277                {
 0278                    if (s[0] == '.')
 0279                    {
 280                        // This should match either domain it self or any subdomain or host
 281                        // .foo.com will match foo.com it self or *.foo.com
 0282                        if (s.AsSpan(1).Equals(input.Host, StringComparison.OrdinalIgnoreCase))
 0283                        {
 0284                            return true;
 285                        }
 0286                        else if (input.Host.EndsWith(s, StringComparison.OrdinalIgnoreCase))
 0287                        {
 0288                            return true;
 289                        }
 290
 0291                    }
 292                    else
 0293                    {
 0294                        if (string.Equals(s, input.Host, StringComparison.OrdinalIgnoreCase))
 0295                        {
 0296                            return true;
 297                        }
 0298                    }
 0299                }
 0300            }
 301
 0302            if (_bypassNetworks != null && IPAddress.TryParse(input.Host, out IPAddress? ip))
 0303            {
 0304                foreach (IPNetwork network in _bypassNetworks)
 0305                {
 0306                    if (network.Contains(ip))
 0307                    {
 0308                        return true;
 309                    }
 0310                }
 0311            }
 312
 0313            return false;
 0314        }
 315
 316        /// <summary>
 317        /// Gets the proxy URI. (iWebProxy interface)
 318        /// </summary>
 319        public Uri? GetProxy(Uri uri)
 0320        {
 0321            return HttpUtilities.IsSupportedNonSecureScheme(uri.Scheme) ? _httpProxyUri : _httpsProxyUri;
 0322        }
 323
 324        /// <summary>
 325        /// Checks if URI is subject to proxy or not.
 326        /// </summary>
 327        public bool IsBypassed(Uri uri)
 0328        {
 0329            return GetProxy(uri) == null ? true : IsMatchInBypassList(uri);
 0330        }
 331
 332        public ICredentials? Credentials
 333        {
 334            get
 0335            {
 0336                return _credentials;
 0337            }
 338            set
 0339            {
 0340                _credentials = value;
 0341            }
 342        }
 343    }
 344}
 345

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpEnvironmentProxy.Windows.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System.Diagnostics.CodeAnalysis;
 5
 6namespace System.Net.Http
 7{
 8    internal sealed partial class HttpEnvironmentProxy : IWebProxy
 9    {
 10        public static bool TryCreate([NotNullWhen(true)] out IWebProxy? proxy)
 011        {
 12            // Get environment variables. Protocol specific take precedence over
 13            // general all_*. On Windows, environment variables are case insensitive.
 14
 015            Uri? httpProxy = null;
 016            if (Environment.GetEnvironmentVariable(EnvCGI) == null)
 017            {
 018                httpProxy = GetUriFromString(Environment.GetEnvironmentVariable(EnvHttpProxyUC));
 019            }
 20
 021            Uri? httpsProxy = GetUriFromString(Environment.GetEnvironmentVariable(EnvHttpsProxyUC));
 22
 023            if (httpProxy == null || httpsProxy == null)
 024            {
 025                Uri? allProxy = GetUriFromString(Environment.GetEnvironmentVariable(EnvAllProxyUC));
 26
 027                httpProxy ??= allProxy;
 028                httpsProxy ??= allProxy;
 029            }
 30
 31            // Do not instantiate if nothing is set.
 32            // Caller may pick some other proxy type.
 033            if (httpProxy == null && httpsProxy == null)
 034            {
 035                proxy = null;
 036                return false;
 37            }
 38
 039            string? noProxy = Environment.GetEnvironmentVariable(EnvNoProxyUC);
 040            proxy = new HttpEnvironmentProxy(httpProxy, httpsProxy, noProxy);
 41
 042            return true;
 043        }
 44    }
 45}
 46