< Summary

Class:Azure.Core.Pipeline.HttpEnvironmentProxy
Assembly:Azure.Core
File(s):C:\Git\azure-sdk-for-net\sdk\core\Azure.Core\src\Pipeline\Internal\HttpEnvironmentProxy.cs
Covered lines:84
Uncovered lines:3
Coverable lines:87
Total lines:263
Line coverage:96.5% (84 of 87)
Covered branches:70
Total branches:72
Branch coverage:97.2% (70 of 72)

Metrics

MethodCyclomatic complexity Line coverage Branch coverage
TryCreate(...)-100%100%
.ctor(...)-100%100%
GetUriFromString(...)-94.87%95.83%
IsMatchInBypassList(...)-100%100%
GetProxy(...)-100%100%
IsBypassed(...)-100%50%
get_Credentials()-100%100%
set_Credentials(...)-0%100%

File(s)

C:\Git\azure-sdk-for-net\sdk\core\Azure.Core\src\Pipeline\Internal\HttpEnvironmentProxy.cs

#LineLine coverage
 1// Copyright (c) Microsoft Corporation. All rights reserved.
 2// Licensed under the MIT License.
 3
 4// Copied from https://raw.githubusercontent.com/dotnet/corefx/master/src/System.Net.Http/src/System/Net/Http/SocketsHtt
 5
 6#nullable disable
 7
 8using System;
 9using System.Net;
 10using System.Collections.Generic;
 11
 12namespace Azure.Core.Pipeline
 13{
 14
 15    internal sealed partial class HttpEnvironmentProxy : IWebProxy
 16    {
 17        private const string EnvAllProxyUC = "ALL_PROXY";
 18        private const string EnvAllProxyLC = "all_proxy";
 19        private const string EnvHttpProxyLC = "http_proxy";
 20        private const string EnvHttpProxyUC = "HTTP_PROXY";
 21        private const string EnvHttpsProxyLC = "https_proxy";
 22        private const string EnvHttpsProxyUC = "HTTPS_PROXY";
 23        private const string EnvNoProxyLC = "no_proxy";
 24        private const string EnvNoProxyUC = "NO_PROXY";
 25        private const string EnvCGI = "GATEWAY_INTERFACE"; // Running in a CGI environment.
 26
 27        private readonly Uri _httpProxyUri;      // String URI for HTTP requests
 28        private readonly Uri _httpsProxyUri;     // String URI for HTTPS requests
 29        private readonly string[] _bypass;// list of domains not to proxy
 30        private readonly ICredentials _credentials;
 31
 32        public static bool TryCreate(out IWebProxy proxy)
 33        {
 34            // Get environment variables. Protocol specific take precedence over
 35            // general all_*, lower case variable has precedence over upper case.
 36            // Note that curl uses HTTPS_PROXY but not HTTP_PROXY.
 37
 72438            Uri httpProxy = GetUriFromString(Environment.GetEnvironmentVariable(EnvHttpProxyLC));
 72439            if (httpProxy == null && Environment.GetEnvironmentVariable(EnvCGI) == null)
 40            {
 70441                httpProxy = GetUriFromString(Environment.GetEnvironmentVariable(EnvHttpProxyUC));
 42            }
 43
 72444            Uri httpsProxy = GetUriFromString(Environment.GetEnvironmentVariable(EnvHttpsProxyLC)) ??
 72445                             GetUriFromString(Environment.GetEnvironmentVariable(EnvHttpsProxyUC));
 46
 72447            if (httpProxy == null || httpsProxy == null)
 48            {
 72249                Uri allProxy = GetUriFromString(Environment.GetEnvironmentVariable(EnvAllProxyLC)) ??
 72250                               GetUriFromString(Environment.GetEnvironmentVariable(EnvAllProxyUC));
 51
 72252                if (httpProxy == null)
 53                {
 70454                    httpProxy = allProxy;
 55                }
 56
 72257                if (httpsProxy == null)
 58                {
 72059                    httpsProxy = allProxy;
 60                }
 61            }
 62
 63            // Do not instantiate if nothing is set.
 64            // Caller may pick some other proxy type.
 72465            if (httpProxy == null && httpsProxy == null)
 66            {
 66667                proxy = null;
 66668                return false;
 69            }
 70
 5871            string noProxy = Environment.GetEnvironmentVariable(EnvNoProxyLC) ??
 5872                             Environment.GetEnvironmentVariable(EnvNoProxyUC);
 5873            proxy = new HttpEnvironmentProxy(httpProxy, httpsProxy, noProxy);
 74
 5875            return true;
 76        }
 77
 5878        private HttpEnvironmentProxy(Uri httpProxy, Uri httpsProxy, string bypassList)
 79        {
 5880            _httpProxyUri = httpProxy;
 5881            _httpsProxyUri = httpsProxy;
 82
 5883            _credentials = HttpEnvironmentProxyCredentials.TryCreate(httpProxy, httpsProxy);
 84
 5885            if (!string.IsNullOrWhiteSpace(bypassList))
 86            {
 1087                string[] list = bypassList.Split(',');
 1088                List<string> tmpList = new List<string>(list.Length);
 89
 6490                foreach (string value in list)
 91                {
 2292                    string tmp = value.Trim();
 2293                    if (tmp.Length > 0)
 94                    {
 2095                        tmpList.Add(tmp);
 96                    }
 97                }
 1098                if (tmpList.Count > 0)
 99                {
 10100                    _bypass = tmpList.ToArray();
 101                }
 102            }
 58103        }
 104
 105        /// <summary>
 106        /// This function will evaluate given string and it will try to convert
 107        /// it to Uri object. The string could contain URI fragment, IP address and  port
 108        /// tuple or just IP address or name. It will return null if parsing fails.
 109        /// </summary>
 110        private static Uri GetUriFromString(string value)
 111        {
 4272112            if (string.IsNullOrEmpty(value))
 113            {
 4196114                return null;
 115            }
 76116            if (value.StartsWith("http://", StringComparison.OrdinalIgnoreCase))
 117            {
 50118                value = value.Substring(7);
 119            }
 120
 76121            string user = null;
 76122            string password = null;
 76123            ushort port = 80;
 124
 125            // Check if there is authentication part with user and possibly password.
 126            // Curl accepts raw text and that may break URI parser.
 76127            int separatorIndex = value.LastIndexOf('@');
 76128            if (separatorIndex != -1)
 129            {
 28130                string auth = value.Substring(0, separatorIndex);
 131
 132                // The User and password may or may not be URL encoded.
 133                // Curl seems to accept both. To match that,
 134                // we do opportunistic decode and we use original string if it fails.
 135                try
 136                {
 28137                    auth = Uri.UnescapeDataString(auth);
 28138                }
 0139                catch { };
 140
 28141                value = value.Substring(separatorIndex + 1);
 28142                separatorIndex = auth.IndexOf(':');
 28143                if (separatorIndex == -1)
 144                {
 6145                    user = auth;
 146                }
 147                else
 148                {
 22149                    user = auth.Substring(0, separatorIndex);
 22150                    password = auth.Substring(separatorIndex + 1);
 151                }
 152            }
 153
 76154            int ipV6AddressEnd = value.IndexOf(']');
 76155            separatorIndex = value.LastIndexOf(':');
 156            string host;
 157            // No ':' or it is part of IPv6 address.
 76158            if (separatorIndex == -1 || (ipV6AddressEnd != -1 && separatorIndex < ipV6AddressEnd))
 159            {
 16160                host = value;
 161            }
 162            else
 163            {
 60164                host = value.Substring(0, separatorIndex);
 60165                int endIndex = separatorIndex + 1;
 166                // Strip any trailing characters after port number.
 304167                while (endIndex < value.Length)
 168                {
 256169                    if (!char.IsDigit(value[endIndex]))
 170                    {
 171                        break;
 172                    }
 244173                    endIndex += 1;
 174                }
 175
 60176                if (!ushort.TryParse(value.Substring(separatorIndex + 1, endIndex - separatorIndex - 1), out port))
 177                {
 0178                    return null;
 179                }
 180            }
 181
 182            try
 183            {
 76184                UriBuilder ub = new UriBuilder("http", host, port);
 76185                if (user != null)
 186                {
 28187                    ub.UserName = Uri.EscapeDataString(user);
 188                }
 189
 76190                if (password != null)
 191                {
 22192                    ub.Password = Uri.EscapeDataString(password);
 193                }
 194
 76195                return ub.Uri;
 196            }
 16197            catch { };
 8198            return null;
 68199        }
 200
 201        /// <summary>
 202        /// This function returns true if given Host match bypass list.
 203        /// Note, that the list is common for http and https.
 204        /// </summary>
 205        private bool IsMatchInBypassList(Uri input)
 206        {
 34207            if (_bypass != null)
 208            {
 116209                foreach (string s in _bypass)
 210                {
 40211                    if (s[0] == '.')
 212                    {
 213                        // This should match either domain it self or any subdomain or host
 214                        // .foo.com will match foo.com it self or *.foo.com
 26215                        if ((s.Length - 1) == input.Host.Length &&
 26216                            string.Compare(s, 1, input.Host, 0, input.Host.Length, StringComparison.OrdinalIgnoreCase) =
 217                        {
 10218                            return true;
 219                        }
 16220                        else if (input.Host.EndsWith(s, StringComparison.OrdinalIgnoreCase))
 221                        {
 2222                            return true;
 223                        }
 224
 225                    }
 226                    else
 227                    {
 14228                        if (string.Equals(s, input.Host, StringComparison.OrdinalIgnoreCase))
 229                        {
 4230                            return true;
 231                        }
 232                    }
 233                }
 234            }
 18235            return false;
 236        }
 237
 238        /// <summary>
 239        /// Gets the proxy URI. (iWebProxy interface).
 240        /// </summary>
 241        public Uri GetProxy(Uri uri)
 242        {
 96243            return uri.Scheme == Uri.UriSchemeHttp ? _httpProxyUri : _httpsProxyUri;
 244        }
 245
 246        /// <summary>
 247        /// Checks if URI is subject to proxy or not.
 248        /// </summary>
 249        public bool IsBypassed(Uri uri)
 250        {
 34251            return GetProxy(uri) == null ? true : IsMatchInBypassList(uri);
 252        }
 253
 254        public ICredentials Credentials
 255        {
 256            get
 257            {
 32258                return _credentials;
 259            }
 0260            set { throw new NotSupportedException(); }
 261        }
 262    }
 263}