/// <summary> /// Allows configuring the <see cref="SocketsHttpHandler"/> instance. The base implementation /// applies settings from <see cref="ForwarderHttpClientContext.NewConfig"/>. /// <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(ForwarderHttpClientContext context, SocketsHttpHandler handler) { var newConfig = context.NewConfig; if (newConfig.SslProtocols.HasValue) { handler.SslOptions.EnabledSslProtocols = newConfig.SslProtocols.Value; } if (newConfig.MaxConnectionsPerServer != null) { handler.MaxConnectionsPerServer = newConfig.MaxConnectionsPerServer.Value; } if (newConfig.DangerousAcceptAnyServerCertificate ?? false) { handler.SslOptions.RemoteCertificateValidationCallback = delegate { return(true); }; } #if NET handler.EnableMultipleHttp2Connections = newConfig.EnableMultipleHttp2Connections.GetValueOrDefault(true); if (newConfig.RequestHeaderEncoding != null) { var encoding = Encoding.GetEncoding(newConfig.RequestHeaderEncoding); handler.RequestHeaderEncodingSelector = (_, _) => encoding; } #endif var webProxy = TryCreateWebProxy(newConfig.WebProxy); if (webProxy != null) { handler.Proxy = webProxy; handler.UseProxy = true; } }
/// <inheritdoc/> public HttpMessageInvoker CreateClient(ForwarderHttpClientContext context) { if (CanReuseOldClient(context)) { Log.ClientReused(_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.ClientCreated(_logger, context.ClusterId); return(new HttpMessageInvoker(middleware, 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(ForwarderHttpClientContext context, HttpMessageHandler handler) { var activityContextHeaders = context.NewConfig.ActivityContextHeaders.GetValueOrDefault(ActivityContextHeaders.BaggageAndCorrelationContext); if (activityContextHeaders != ActivityContextHeaders.None) { handler = new ActivityPropagationHandler(activityContextHeaders, handler); } return(handler); }
protected override HttpMessageHandler WrapHandler(ForwarderHttpClientContext context, HttpMessageHandler handler) { handler = base.WrapHandler(context, handler); return(new DiagnosticsHandler(handler)); }
/// <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(ForwarderHttpClientContext context) { return(context.OldClient != null && context.NewConfig == context.OldConfig); }
protected override void ConfigureHandler(ForwarderHttpClientContext context, SocketsHttpHandler handler) { base.ConfigureHandler(context, handler); _configureClient(context, handler); }