< Summary

Information
Class: System.Net.Http.HttpClientHandler
Assembly: System.Net.Http
File(s): D:\runner\runtime\src\libraries\System.Net.Http\src\System\Net\Http\HttpClientHandler.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 122
Coverable lines: 122
Total lines: 388
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 30
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor()100%110%
Dispose(...)0%440%
Send(...)100%110%
SendAsync(...)100%110%
ThrowForModifiedManagedSslOptionsIfStarted()100%110%

File(s)

D:\runner\runtime\src\libraries\System.Net.Http\src\System\Net\Http\HttpClientHandler.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.Globalization;
 5using System.Net.Security;
 6using System.Collections.Generic;
 7using System.Runtime.Versioning;
 8using System.Security.Authentication;
 9using System.Security.Cryptography.X509Certificates;
 10using System.Threading;
 11using System.Threading.Tasks;
 12using System.Diagnostics.Metrics;
 13#if TARGET_WASI
 14using System.Diagnostics;
 15using System.Net.Http.Metrics;
 16using HttpHandlerType = System.Net.Http.WasiHttpHandler;
 17#elif TARGET_BROWSER
 18using System.Diagnostics;
 19using System.Net.Http.Metrics;
 20using HttpHandlerType = System.Net.Http.BrowserHttpHandler;
 21#else
 22using HttpHandlerType = System.Net.Http.SocketsHttpHandler;
 23#endif
 24
 25namespace System.Net.Http
 26{
 27    public partial class HttpClientHandler : HttpMessageHandler
 28    {
 29        private readonly HttpHandlerType _underlyingHandler;
 30
 31#if TARGET_BROWSER || TARGET_WASI
 32        private IMeterFactory? _meterFactory;
 33        private HttpMessageHandler? _firstHandler; // DiagnosticsHandler or MetricsHandler, depending on global configur
 34
 35        private HttpMessageHandler Handler
 36        {
 37            get
 38            {
 39                if (_firstHandler != null)
 40                {
 41                    return _firstHandler;
 42                }
 43
 44                HttpMessageHandler handler = _underlyingHandler;
 45
 46                // MetricsHandler should be descendant of DiagnosticsHandler in the handler chain to make sure the 'http
 47                // metric is recorded before stopping the request Activity. This is needed to make sure that our telemet
 48                // Since HttpClientHandler.Proxy is unsupported on most platforms, don't bother passing it to telemetry 
 49                if (GlobalHttpSettings.MetricsHandler.IsGloballyEnabled)
 50                {
 51                    handler = new MetricsHandler(handler, _meterFactory, proxy: null, out _);
 52                }
 53                if (GlobalHttpSettings.DiagnosticsHandler.EnableActivityPropagation)
 54                {
 55                    handler = new DiagnosticsHandler(handler, DistributedContextPropagator.Current, proxy: null);
 56                }
 57
 58                // Ensure a single handler is used for all requests.
 59                if (Interlocked.CompareExchange(ref _firstHandler, handler, null) != null)
 60                {
 61                    handler.Dispose();
 62                }
 63
 64                return _firstHandler;
 65            }
 66        }
 67#else
 068        private HttpHandlerType Handler => _underlyingHandler;
 69#endif
 70
 71        private volatile bool _disposed;
 72
 073        public HttpClientHandler()
 074        {
 075            _underlyingHandler = new HttpHandlerType();
 76
 077            ClientCertificateOptions = ClientCertificateOption.Manual;
 078        }
 79
 80        protected override void Dispose(bool disposing)
 081        {
 082            if (disposing && !_disposed)
 083            {
 084                _disposed = true;
 085                _underlyingHandler.Dispose();
 086            }
 87
 088            base.Dispose(disposing);
 089        }
 90
 091        public virtual bool SupportsAutomaticDecompression => HttpHandlerType.SupportsAutomaticDecompression;
 092        public virtual bool SupportsProxy => HttpHandlerType.SupportsProxy;
 093        public virtual bool SupportsRedirectConfiguration => HttpHandlerType.SupportsRedirectConfiguration;
 94
 95        /// <summary>
 96        /// Gets or sets the <see cref="IMeterFactory"/> to create a custom <see cref="Meter"/> for the <see cref="HttpC
 97        /// </summary>
 98        /// <remarks>
 99        /// When <see cref="MeterFactory"/> is set to a non-<see langword="null"/> value, all metrics emitted by the <se
 100        /// will be recorded using the <see cref="Meter"/> provided by the <see cref="IMeterFactory"/>.
 101        /// </remarks>
 102        [CLSCompliant(false)]
 103        public IMeterFactory? MeterFactory
 104        {
 105#if TARGET_BROWSER || TARGET_WASI
 106            get => _meterFactory;
 107            set
 108            {
 109                ObjectDisposedException.ThrowIf(_disposed, this);
 110                if (_firstHandler != null)
 111                {
 112                    throw new InvalidOperationException(SR.net_http_operation_started);
 113                }
 114                _meterFactory = value;
 115            }
 116#else
 0117            get => _underlyingHandler.MeterFactory;
 0118            set => _underlyingHandler.MeterFactory = value;
 119#endif
 120        }
 121
 122        [UnsupportedOSPlatform("browser")]
 123        public bool UseCookies
 124        {
 0125            get => _underlyingHandler.UseCookies;
 0126            set => _underlyingHandler.UseCookies = value;
 127        }
 128
 129        [UnsupportedOSPlatform("browser")]
 130        public CookieContainer CookieContainer
 131        {
 0132            get => _underlyingHandler.CookieContainer;
 133            set
 0134            {
 0135                ArgumentNullException.ThrowIfNull(value);
 136
 0137                _underlyingHandler.CookieContainer = value;
 0138            }
 139        }
 140
 141        [UnsupportedOSPlatform("browser")]
 142        public DecompressionMethods AutomaticDecompression
 143        {
 0144            get => _underlyingHandler.AutomaticDecompression;
 0145            set => _underlyingHandler.AutomaticDecompression = value;
 146        }
 147
 148        [UnsupportedOSPlatform("browser")]
 149        public bool UseProxy
 150        {
 0151            get => _underlyingHandler.UseProxy;
 0152            set => _underlyingHandler.UseProxy = value;
 153        }
 154
 155        [UnsupportedOSPlatform("browser")]
 156        [UnsupportedOSPlatform("ios")]
 157        [UnsupportedOSPlatform("tvos")]
 158        public IWebProxy? Proxy
 159        {
 0160            get => _underlyingHandler.Proxy;
 0161            set => _underlyingHandler.Proxy = value;
 162        }
 163
 164        [UnsupportedOSPlatform("browser")]
 165        public ICredentials? DefaultProxyCredentials
 166        {
 0167            get => _underlyingHandler.DefaultProxyCredentials;
 0168            set => _underlyingHandler.DefaultProxyCredentials = value;
 169        }
 170
 171        [UnsupportedOSPlatform("browser")]
 172        public bool PreAuthenticate
 173        {
 0174            get => _underlyingHandler.PreAuthenticate;
 0175            set => _underlyingHandler.PreAuthenticate = value;
 176        }
 177
 178        [UnsupportedOSPlatform("browser")]
 179        public bool UseDefaultCredentials
 180        {
 181            // SocketsHttpHandler doesn't have a separate UseDefaultCredentials property.  There
 182            // is just a Credentials property.  So, we need to map the behavior.
 0183            get => _underlyingHandler.Credentials == CredentialCache.DefaultCredentials;
 184            set
 0185            {
 0186                if (value)
 0187                {
 0188                    _underlyingHandler.Credentials = CredentialCache.DefaultCredentials;
 0189                }
 190                else
 0191                {
 0192                    if (_underlyingHandler.Credentials == CredentialCache.DefaultCredentials)
 0193                    {
 194                        // Only clear out the Credentials property if it was a DefaultCredentials.
 0195                        _underlyingHandler.Credentials = null;
 0196                    }
 0197                }
 0198            }
 199        }
 200
 201        [UnsupportedOSPlatform("browser")]
 202        public ICredentials? Credentials
 203        {
 0204            get => _underlyingHandler.Credentials;
 0205            set => _underlyingHandler.Credentials = value;
 206        }
 207
 208        public bool AllowAutoRedirect
 209        {
 0210            get => _underlyingHandler.AllowAutoRedirect;
 0211            set => _underlyingHandler.AllowAutoRedirect = value;
 212        }
 213
 214        [UnsupportedOSPlatform("browser")]
 215        public int MaxAutomaticRedirections
 216        {
 0217            get => _underlyingHandler.MaxAutomaticRedirections;
 0218            set => _underlyingHandler.MaxAutomaticRedirections = value;
 219        }
 220
 221        [UnsupportedOSPlatform("browser")]
 222        public int MaxConnectionsPerServer
 223        {
 0224            get => _underlyingHandler.MaxConnectionsPerServer;
 0225            set => _underlyingHandler.MaxConnectionsPerServer = value;
 226        }
 227
 228        public long MaxRequestContentBufferSize
 229        {
 230            // This property is not supported. In the .NET Framework it was only used when the handler needed to
 231            // automatically buffer the request content. That only happened if neither 'Content-Length' nor
 232            // 'Transfer-Encoding: chunked' request headers were specified. So, the handler thus needed to buffer
 233            // in the request content to determine its length and then would choose 'Content-Length' semantics when
 234            // POST'ing. In .NET Core, the handler will resolve the ambiguity by always choosing
 235            // 'Transfer-Encoding: chunked'. The handler will never automatically buffer in the request content.
 236            get
 0237            {
 0238                return 0; // Returning zero is appropriate since in .NET Framework it means no limit.
 0239            }
 240
 241            set
 0242            {
 0243                ArgumentOutOfRangeException.ThrowIfNegative(value);
 244
 0245                if (value > HttpContent.MaxBufferSize)
 0246                {
 0247                    throw new ArgumentOutOfRangeException(nameof(value), value,
 0248                        SR.Format(CultureInfo.InvariantCulture, SR.net_http_content_buffersize_limit,
 0249                        HttpContent.MaxBufferSize));
 250                }
 251
 0252                ObjectDisposedException.ThrowIf(_disposed, this);
 253
 254                // No-op on property setter.
 0255            }
 256        }
 257
 258        [UnsupportedOSPlatform("browser")]
 259        public int MaxResponseHeadersLength
 260        {
 0261            get => _underlyingHandler.MaxResponseHeadersLength;
 0262            set => _underlyingHandler.MaxResponseHeadersLength = value;
 263        }
 264
 265        public ClientCertificateOption ClientCertificateOptions
 266        {
 0267            get => _underlyingHandler.ClientCertificateOptions;
 268            set
 0269            {
 0270                switch (value)
 271                {
 272                    case ClientCertificateOption.Manual:
 273#if !(TARGET_BROWSER || TARGET_WASI)
 0274                        ThrowForModifiedManagedSslOptionsIfStarted();
 0275                        _underlyingHandler.SslOptions.LocalCertificateSelectionCallback = (sender, targetHost, localCert
 276#endif
 0277                        break;
 278
 279                    case ClientCertificateOption.Automatic:
 280#if !(TARGET_BROWSER || TARGET_WASI)
 0281                        ThrowForModifiedManagedSslOptionsIfStarted();
 0282                        _underlyingHandler.SslOptions.LocalCertificateSelectionCallback = (sender, targetHost, localCert
 283#endif
 0284                        break;
 285
 286                    default:
 0287                        throw new ArgumentOutOfRangeException(nameof(value));
 288                }
 0289                _underlyingHandler.ClientCertificateOptions = value;
 0290            }
 291        }
 292
 293        [UnsupportedOSPlatform("browser")]
 294        public X509CertificateCollection ClientCertificates
 295        {
 296            get
 0297            {
 0298                if (ClientCertificateOptions != ClientCertificateOption.Manual)
 0299                {
 0300                    throw new InvalidOperationException(SR.Format(SR.net_http_invalid_enable_first, nameof(ClientCertifi
 301                }
 302
 0303                return _underlyingHandler.SslOptions.ClientCertificates ??
 0304                    (_underlyingHandler.SslOptions.ClientCertificates = new X509CertificateCollection());
 0305            }
 306        }
 307
 308        [UnsupportedOSPlatform("browser")]
 309        public Func<HttpRequestMessage, X509Certificate2?, X509Chain?, SslPolicyErrors, bool>? ServerCertificateCustomVa
 310        {
 311#if TARGET_BROWSER || TARGET_WASI
 312            get => throw new PlatformNotSupportedException();
 313            set => throw new PlatformNotSupportedException();
 314#else
 0315            get => (_underlyingHandler.SslOptions.RemoteCertificateValidationCallback?.Target as ConnectHelper.Certifica
 316            set
 0317            {
 0318                ThrowForModifiedManagedSslOptionsIfStarted();
 0319                _underlyingHandler.SslOptions.RemoteCertificateValidationCallback = value != null ?
 0320                    new ConnectHelper.CertificateCallbackMapper(value).ForSocketsHttpHandler :
 0321                    null;
 0322            }
 323#endif
 324        }
 325
 326        [UnsupportedOSPlatform("browser")]
 327        public bool CheckCertificateRevocationList
 328        {
 0329            get => _underlyingHandler.SslOptions.CertificateRevocationCheckMode == X509RevocationMode.Online;
 330            set
 0331            {
 0332                ThrowForModifiedManagedSslOptionsIfStarted();
 0333                _underlyingHandler.SslOptions.CertificateRevocationCheckMode = value ? X509RevocationMode.Online : X509R
 0334            }
 335        }
 336
 337        [UnsupportedOSPlatform("browser")]
 338        public SslProtocols SslProtocols
 339        {
 0340            get => _underlyingHandler.SslOptions.EnabledSslProtocols;
 341            set
 0342            {
 0343                ThrowForModifiedManagedSslOptionsIfStarted();
 0344                _underlyingHandler.SslOptions.EnabledSslProtocols = value;
 0345            }
 346        }
 347
 0348        public IDictionary<string, object?> Properties => _underlyingHandler.Properties;
 349
 350        //
 351        // Attributes are commented out due to https://github.com/dotnet/arcade/issues/7585
 352        // API compat will fail until this is fixed
 353        //
 354        [UnsupportedOSPlatform("android")]
 355        [UnsupportedOSPlatform("browser")]
 356        [UnsupportedOSPlatform("ios")]
 357        [UnsupportedOSPlatform("tvos")]
 358        protected internal override HttpResponseMessage Send(HttpRequestMessage request, CancellationToken cancellationT
 0359        {
 360#if TARGET_BROWSER || TARGET_WASI
 361            throw new PlatformNotSupportedException();
 362#else
 0363            ArgumentNullException.ThrowIfNull(request);
 0364            return Handler.Send(request, cancellationToken);
 365#endif
 0366        }
 367
 368        protected internal override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken ca
 0369        {
 0370            ArgumentNullException.ThrowIfNull(request);
 0371            return Handler.SendAsync(request, cancellationToken);
 0372        }
 373
 374        // lazy-load the validator func so it can be trimmed by the ILLinker if it isn't used.
 375        [UnsupportedOSPlatform("browser")]
 376        public static Func<HttpRequestMessage, X509Certificate2?, X509Chain?, SslPolicyErrors, bool> DangerousAcceptAnyS
 0377            field ??
 0378            Interlocked.CompareExchange(ref field, delegate { return true; }, null) ??
 0379            field;
 380
 381        private void ThrowForModifiedManagedSslOptionsIfStarted()
 0382        {
 383            // Hack to trigger an InvalidOperationException if a property that's stored on
 384            // SslOptions is changed, since SslOptions itself does not do any such checks.
 0385            _underlyingHandler.SslOptions = _underlyingHandler.SslOptions;
 0386        }
 387    }
 388}

Methods/Properties

Handler()
.ctor()
Dispose(System.Boolean)
SupportsAutomaticDecompression()
SupportsProxy()
SupportsRedirectConfiguration()
MeterFactory()
MeterFactory(System.Diagnostics.Metrics.IMeterFactory)
UseCookies()
UseCookies(System.Boolean)
CookieContainer()
CookieContainer(System.Net.CookieContainer)
AutomaticDecompression()
AutomaticDecompression(System.Net.DecompressionMethods)
UseProxy()
UseProxy(System.Boolean)
Proxy()
Proxy(System.Net.IWebProxy)
DefaultProxyCredentials()
DefaultProxyCredentials(System.Net.ICredentials)
PreAuthenticate()
PreAuthenticate(System.Boolean)
UseDefaultCredentials()
UseDefaultCredentials(System.Boolean)
Credentials()
Credentials(System.Net.ICredentials)
AllowAutoRedirect()
AllowAutoRedirect(System.Boolean)
MaxAutomaticRedirections()
MaxAutomaticRedirections(System.Int32)
MaxConnectionsPerServer()
MaxConnectionsPerServer(System.Int32)
MaxRequestContentBufferSize()
MaxRequestContentBufferSize(System.Int64)
MaxResponseHeadersLength()
MaxResponseHeadersLength(System.Int32)
ClientCertificateOptions()
ClientCertificateOptions(System.Net.Http.ClientCertificateOption)
ClientCertificates()
ServerCertificateCustomValidationCallback()
ServerCertificateCustomValidationCallback(System.Func`5<System.Net.Http.HttpRequestMessage,System.Security.Cryptography.X509Certificates.X509Certificate2,System.Security.Cryptography.X509Certificates.X509Chain,System.Net.Security.SslPolicyErrors,System.Boolean>)
CheckCertificateRevocationList()
CheckCertificateRevocationList(System.Boolean)
SslProtocols()
SslProtocols(System.Security.Authentication.SslProtocols)
Properties()
Send(System.Net.Http.HttpRequestMessage,System.Threading.CancellationToken)
SendAsync(System.Net.Http.HttpRequestMessage,System.Threading.CancellationToken)
DangerousAcceptAnyServerCertificateValidator()
ThrowForModifiedManagedSslOptionsIfStarted()