/// <inheritdoc/>
        public HttpMessageInvoker CreateClient(ProxyHttpClientContext context)
        {
            if (CanReuseOldClient(context))
            {
                Log.ProxyClientReused(_logger, context.ClusterId);
                return(context.OldClient);
            }

            var handler = new SocketsHttpHandler
            {
                UseProxy               = false,
                AllowAutoRedirect      = false,
                AutomaticDecompression = DecompressionMethods.None,
                UseCookies             = false

                                         // NOTE: MaxResponseHeadersLength = 64, which means up to 64 KB of headers are allowed by default as of .NET Core 3.1.
            };

            ConfigureHandler(context, handler);

            var middleware = WrapHandler(context, handler);

            Log.ProxyClientCreated(_logger, context.ClusterId);

            return(new HttpMessageInvoker(middleware, disposeHandler: true));
        }
        /// <inheritdoc/>
        public HttpMessageInvoker CreateClient(ProxyHttpClientContext context)
        {
            if (CanReuseOldClient(context))
            {
                Log.ProxyClientReused(_logger, context.ClusterId);
                return(context.OldClient);
            }

            var newClientOptions = context.NewOptions;
            var handler          = new SocketsHttpHandler
            {
                UseProxy               = false,
                AllowAutoRedirect      = false,
                AutomaticDecompression = DecompressionMethods.None,
                UseCookies             = false

                                         // NOTE: MaxResponseHeadersLength = 64, which means up to 64 KB of headers are allowed by default as of .NET Core 3.1.
            };

            if (newClientOptions.SslProtocols.HasValue)
            {
                handler.SslOptions.EnabledSslProtocols = newClientOptions.SslProtocols.Value;
            }
            if (newClientOptions.ClientCertificate != null)
            {
                handler.SslOptions.ClientCertificates = new X509CertificateCollection
                {
                    newClientOptions.ClientCertificate
                };
            }
            if (newClientOptions.MaxConnectionsPerServer != null)
            {
                handler.MaxConnectionsPerServer = newClientOptions.MaxConnectionsPerServer.Value;
            }
            if (newClientOptions.DangerousAcceptAnyServerCertificate ?? false)
            {
                handler.SslOptions.RemoteCertificateValidationCallback = delegate { return(true); };
            }
#if NET
            handler.EnableMultipleHttp2Connections = newClientOptions.EnableMultipleHttp2Connections.GetValueOrDefault(true);

            if (newClientOptions.RequestHeaderEncoding != null)
            {
                handler.RequestHeaderEncodingSelector = (_, _) => newClientOptions.RequestHeaderEncoding;
            }
#endif

            Log.ProxyClientCreated(_logger, context.ClusterId);

            var activityContextHeaders = newClientOptions.ActivityContextHeaders.GetValueOrDefault(ActivityContextHeaders.BaggageAndCorrelationContext);
            if (activityContextHeaders != ActivityContextHeaders.None)
            {
                return(new HttpMessageInvoker(new ActivityPropagationHandler(activityContextHeaders, handler), disposeHandler: true));
            }

            return(new HttpMessageInvoker(handler, disposeHandler: true));
        }
        /// <summary>
        /// Adds any wrapping middleware around the <see cref="HttpMessageHandler"/>.
        /// The base implementation conditionally includes the <see cref="ActivityPropagationHandler"/>.
        /// </summary>
        protected virtual HttpMessageHandler WrapHandler(ProxyHttpClientContext context, HttpMessageHandler handler)
        {
            var activityContextHeaders = context.NewOptions.ActivityContextHeaders.GetValueOrDefault(ActivityContextHeaders.BaggageAndCorrelationContext);

            if (activityContextHeaders != ActivityContextHeaders.None)
            {
                handler = new ActivityPropagationHandler(activityContextHeaders, handler);
            }

            return(handler);
        }
        /// <summary>
        /// Allows configuring the <see cref="SocketsHttpHandler"/> instance. The base implementation
        /// applies settings from <see cref="ProxyHttpClientContext.NewOptions"/>.
        /// <see cref="SocketsHttpHandler.UseProxy"/>, <see cref="SocketsHttpHandler.AllowAutoRedirect"/>,
        /// <see cref="SocketsHttpHandler.AutomaticDecompression"/>, and <see cref="SocketsHttpHandler.UseCookies"/>
        /// are disabled prior to this call.
        /// </summary>
        protected virtual void ConfigureHandler(ProxyHttpClientContext context, SocketsHttpHandler handler)
        {
            var newClientOptions = context.NewOptions;

            if (newClientOptions.SslProtocols.HasValue)
            {
                handler.SslOptions.EnabledSslProtocols = newClientOptions.SslProtocols.Value;
            }
            if (newClientOptions.ClientCertificate != null)
            {
                handler.SslOptions.ClientCertificates = new X509CertificateCollection
                {
                    newClientOptions.ClientCertificate
                };
            }
            if (newClientOptions.MaxConnectionsPerServer != null)
            {
                handler.MaxConnectionsPerServer = newClientOptions.MaxConnectionsPerServer.Value;
            }
            if (newClientOptions.DangerousAcceptAnyServerCertificate ?? false)
            {
                handler.SslOptions.RemoteCertificateValidationCallback = delegate { return(true); };
            }
#if NET
            handler.EnableMultipleHttp2Connections = newClientOptions.EnableMultipleHttp2Connections.GetValueOrDefault(true);

            if (newClientOptions.RequestHeaderEncoding != null)
            {
                handler.RequestHeaderEncodingSelector = (_, _) => newClientOptions.RequestHeaderEncoding;
            }
#endif
            var webProxy = TryCreateWebProxy(newClientOptions.WebProxy);
            if (webProxy != null)
            {
                handler.Proxy    = webProxy;
                handler.UseProxy = true;
            }
        }
 protected override void ConfigureHandler(ProxyHttpClientContext context, SocketsHttpHandler handler)
 {
     base.ConfigureHandler(context, handler);
     _configureClient(context, handler);
 }
Exemplo n.º 6
0
 private static bool CanReuseOldClient(ProxyHttpClientContext context)
 {
     return(context.OldClient != null && context.NewOptions == context.OldOptions);
 }
 /// <summary>
 /// Checks if the options have changed since the old client was created. If not then the
 /// old client will be re-used. Re-use can avoid the latency of creating new connections.
 /// </summary>
 protected virtual bool CanReuseOldClient(ProxyHttpClientContext context)
 {
     return(context.OldClient != null && context.NewOptions == context.OldOptions);
 }