< Summary

Line coverage
0%
Covered lines: 0
Uncovered lines: 157
Coverable lines: 157
Total lines: 353
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 70
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%220%
File 1: GetUriFromString(...)0%38380%
File 1: IsMatchInBypassList(...)0%12120%
File 1: GetProxy(...)0%220%
File 1: IsBypassed(...)0%220%
File 2: TryCreate(...)0%14140%

File(s)

D:\runner\runtime\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
 4namespace System.Net.Http
 5{
 6    internal sealed class HttpEnvironmentProxyCredentials : ICredentials
 7    {
 8        // Wrapper class for cases when http and https has different authentication.
 9        private readonly NetworkCredential? _httpCred;
 10        private readonly NetworkCredential? _httpsCred;
 11        private readonly Uri? _httpProxy;
 12        private readonly Uri? _httpsProxy;
 13
 14        public HttpEnvironmentProxyCredentials(Uri? httpProxy, NetworkCredential? httpCred,
 15                                                Uri? httpsProxy, NetworkCredential? httpsCred)
 16        {
 17            _httpCred = httpCred;
 18            _httpsCred = httpsCred;
 19            _httpProxy = httpProxy;
 20            _httpsProxy = httpsProxy;
 21        }
 22
 23        public NetworkCredential? GetCredential(Uri? uri, string authType)
 24        {
 25            if (uri == null)
 26            {
 27                return null;
 28            }
 29            return uri.Equals(_httpProxy) ? _httpCred :
 30                   uri.Equals(_httpsProxy) ? _httpsCred : null;
 31        }
 32
 33        public static HttpEnvironmentProxyCredentials? TryCreate(Uri? httpProxy, Uri? httpsProxy)
 34        {
 35            NetworkCredential? httpCred = null;
 36            NetworkCredential? httpsCred = null;
 37
 38            if (httpProxy != null)
 39            {
 40                httpCred = GetCredentialsFromString(httpProxy.UserInfo);
 41            }
 42            if (httpsProxy != null)
 43            {
 44                httpsCred = GetCredentialsFromString(httpsProxy.UserInfo);
 45            }
 46            if (httpCred == null && httpsCred == null)
 47            {
 48                return null;
 49            }
 50            return new HttpEnvironmentProxyCredentials(httpProxy, httpCred, httpsProxy, httpsCred);
 51        }
 52
 53        /// <summary>
 54        /// Converts string containing user:password to NetworkCredential object
 55        /// </summary>
 56        private static NetworkCredential? GetCredentialsFromString(string? value)
 57        {
 58            if (string.IsNullOrWhiteSpace(value))
 59            {
 60                return null;
 61            }
 62
 63            if (value == ":")
 64            {
 65                return CredentialCache.DefaultNetworkCredentials;
 66            }
 67
 68            value = Uri.UnescapeDataString(value);
 69
 70            string password = "";
 71            string? domain = null;
 72            int idx = value.IndexOf(':');
 73            if (idx != -1)
 74            {
 75                password = value.Substring(idx + 1);
 76                value = value.Substring(0, idx);
 77            }
 78
 79            idx = value.IndexOf('\\');
 80            if (idx != -1)
 81            {
 82                domain = value.Substring(0, idx);
 83                value = value.Substring(idx + 1);
 84            }
 85
 86            return new NetworkCredential(value, password, domain);
 87        }
 88    }
 89
 90    internal sealed partial class HttpEnvironmentProxy : IWebProxy
 91    {
 92        private const string EnvAllProxyUC = "ALL_PROXY";
 93        private const string EnvHttpProxyUC = "HTTP_PROXY";
 94        private const string EnvHttpsProxyUC = "HTTPS_PROXY";
 95        private const string EnvNoProxyUC = "NO_PROXY";
 96        private const string EnvCGI = "GATEWAY_INTERFACE"; // Running in a CGI environment.
 97
 98        private readonly Uri? _httpProxyUri;       // String URI for HTTP requests
 99        private readonly Uri? _httpsProxyUri;      // String URI for HTTPS requests
 100        private readonly string[]? _bypass;        // list of domains not to proxy
 101        private ICredentials? _credentials;
 102
 0103        private HttpEnvironmentProxy(Uri? httpProxy, Uri? httpsProxy, string? bypassList)
 0104        {
 0105            _httpProxyUri = httpProxy;
 0106            _httpsProxyUri = httpsProxy;
 107
 0108            _credentials = HttpEnvironmentProxyCredentials.TryCreate(httpProxy, httpsProxy);
 0109            _bypass = bypassList?.Split(',', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
 0110        }
 111
 112        /// <summary>
 113        /// Attempt to parse a partial Uri string into a Uri object.
 114        /// The string may contain the scheme, user info, host, and port. The host is the only required part.
 115        /// Example expected inputs: contoso.com, contoso.com:8080, http://contoso.com/, user@contoso.com.
 116        /// </summary>
 117        /// <returns><see langword="null"/> if parsing fails.</returns>
 118        private static Uri? GetUriFromString(string? value)
 0119        {
 0120            if (string.IsNullOrEmpty(value))
 0121            {
 0122                return null;
 123            }
 124
 0125            int hostIndex = 0;
 0126            string protocol = "http";
 0127            ushort port = 80;
 128
 0129            if (value.StartsWith("http://", StringComparison.OrdinalIgnoreCase))
 0130            {
 0131                hostIndex = 7;
 0132            }
 0133            else if (value.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
 0134            {
 0135                hostIndex = 8;
 0136                protocol = "https";
 0137                port = 443;
 0138            }
 0139            else if (value.StartsWith("socks4://", StringComparison.OrdinalIgnoreCase))
 0140            {
 0141                hostIndex = 9;
 0142                protocol = "socks4";
 0143            }
 0144            else if (value.StartsWith("socks5://", StringComparison.OrdinalIgnoreCase))
 0145            {
 0146                hostIndex = 9;
 0147                protocol = "socks5";
 0148            }
 0149            else if (value.StartsWith("socks4a://", StringComparison.OrdinalIgnoreCase))
 0150            {
 0151                hostIndex = 10;
 0152                protocol = "socks4a";
 0153            }
 154
 0155            if (hostIndex > 0)
 0156            {
 0157                value = value.Substring(hostIndex);
 0158            }
 159
 0160            string? user = null;
 0161            string? password = null;
 162            string host;
 163
 164            // Check if there is authentication part with user and possibly password.
 165            // Curl accepts raw text and that may break URI parser.
 0166            int separatorIndex = value.LastIndexOf('@');
 0167            if (separatorIndex != -1)
 0168            {
 169                // The User and password may or may not be URL encoded.
 170                // Curl seems to accept both. To match that, we also decode the value.
 0171                string auth = Uri.UnescapeDataString(value.AsSpan(0, separatorIndex));
 172
 0173                value = value.Substring(separatorIndex + 1);
 0174                separatorIndex = auth.IndexOf(':');
 0175                if (separatorIndex == -1)
 0176                {
 0177                    user = auth;
 0178                }
 179                else
 0180                {
 0181                    user = auth.Substring(0, separatorIndex);
 0182                    password = auth.Substring(separatorIndex + 1);
 0183                }
 0184            }
 185
 186            // We expect inputs to not contain the path/query/fragment, but we do handle some simple cases like a traili
 187            // An arbitrary path can break this parsing logic, but we expect environment variables to be trusted and wel
 0188            int delimiterIndex = value.IndexOfAny('/', '?', '#');
 0189            if (delimiterIndex >= 0)
 0190            {
 0191                value = value.Substring(0, delimiterIndex);
 0192            }
 193
 0194            int ipV6AddressEnd = value.IndexOf(']');
 0195            separatorIndex = value.LastIndexOf(':');
 196            // No ':' or it is part of IPv6 address.
 0197            if (separatorIndex == -1 || (ipV6AddressEnd != -1 && separatorIndex < ipV6AddressEnd))
 0198            {
 0199                host = value;
 0200            }
 201            else
 0202            {
 0203                host = value.Substring(0, separatorIndex);
 204
 0205                if (!ushort.TryParse(value.AsSpan(separatorIndex + 1), out port))
 0206                {
 0207                    return null;
 208                }
 0209            }
 210
 211            try
 0212            {
 0213                UriBuilder ub = new UriBuilder(protocol, host, port);
 0214                if (user != null)
 0215                {
 0216                    ub.UserName = Uri.EscapeDataString(user);
 0217                }
 218
 0219                if (password != null)
 0220                {
 0221                    ub.Password = Uri.EscapeDataString(password);
 0222                }
 223
 0224                Uri uri = ub.Uri;
 225
 226                // if both user and password exist and are empty we should preserve that and use default credentials.
 227                // UriBuilder does not handle that now e.g. does not distinguish between empty and missing.
 0228                if (user == "" && password == "")
 0229                {
 0230                    Span<Range> tokens = stackalloc Range[3];
 0231                    ReadOnlySpan<char> uriSpan = uri.ToString();
 0232                    if (uriSpan.Split(tokens, '/') == 3)
 0233                    {
 0234                        uri = new Uri($"{uriSpan[tokens[0]]}//:@{uriSpan[tokens[2]]}");
 0235                    }
 0236                }
 237
 0238                return uri;
 239            }
 0240            catch { };
 0241            return null;
 0242        }
 243
 244        /// <summary>
 245        /// This function returns true if given Host match bypass list.
 246        /// Note, that the list is common for http and https.
 247        /// </summary>
 248        private bool IsMatchInBypassList(Uri input)
 0249        {
 0250            if (_bypass != null)
 0251            {
 0252                foreach (string s in _bypass)
 0253                {
 0254                    if (s[0] == '.')
 0255                    {
 256                        // This should match either domain it self or any subdomain or host
 257                        // .foo.com will match foo.com it self or *.foo.com
 0258                        if (s.AsSpan(1).Equals(input.Host, StringComparison.OrdinalIgnoreCase))
 0259                        {
 0260                            return true;
 261                        }
 0262                        else if (input.Host.EndsWith(s, StringComparison.OrdinalIgnoreCase))
 0263                        {
 0264                            return true;
 265                        }
 266
 0267                    }
 268                    else
 0269                    {
 0270                        if (string.Equals(s, input.Host, StringComparison.OrdinalIgnoreCase))
 0271                        {
 0272                            return true;
 273                        }
 0274                    }
 0275                }
 0276            }
 0277            return false;
 0278        }
 279
 280        /// <summary>
 281        /// Gets the proxy URI. (iWebProxy interface)
 282        /// </summary>
 283        public Uri? GetProxy(Uri uri)
 0284        {
 0285            return HttpUtilities.IsSupportedNonSecureScheme(uri.Scheme) ? _httpProxyUri : _httpsProxyUri;
 0286        }
 287
 288        /// <summary>
 289        /// Checks if URI is subject to proxy or not.
 290        /// </summary>
 291        public bool IsBypassed(Uri uri)
 0292        {
 0293            return GetProxy(uri) == null ? true : IsMatchInBypassList(uri);
 0294        }
 295
 296        public ICredentials? Credentials
 297        {
 298            get
 0299            {
 0300                return _credentials;
 0301            }
 302            set
 0303            {
 0304                _credentials = value;
 0305            }
 306        }
 307    }
 308}

D:\runner\runtime\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}