HttpClient accepts only one HttpMessageHandler. I have two of them.
HttpClientHandler clientHandler = GetClientHandler();
SocketsHttpHandler socketsHandler = GetSocketsHandler();
HttpClient client = new( /* how to put two handlers here? */ );
At least for .NET 6+, when looking at the source code of HttpClientHandler, one can see that under the covers, this class simply uses a SocketsHttpHandler
and maps most properties 1-to-1. So, you can just use a SocketsHttpHandler
yourself and set all the same properties. See the source code for reference on any custom logic that the HttpClientHandler
may be doing that you may want to consider doing against the SocketsHttpHandler
.
Further comments from folks at Microsoft can be seen here, encouraging use of SocketsHttpHandler
.
With .NET 8, I'm able to get access to the private Handler
property of HttpClientHandler
(you can see it in the debugger), which returns SocketsHttpHandler
, and set properties on it like ConnectionTimeout
, which is not exposed through HttpClientHandler
.
Obviously, this code is prone to break due to dependencies on internals which may change over time, but it's easy to reason with and doesn't require reimplementing HttpClientHandler
.
public class CustomHttpClientHandler : HttpClientHandler
{
public TimeSpan ConnectTimeout { get; }
public CustomHttpClientHandler(TimeSpan connectTimeout)
{
ConnectTimeout = connectTimeout;
if (typeof(HttpClientHandler)
.GetProperty("Handler", BindingFlags.NonPublic | BindingFlags.Instance)?
.GetValue(this) is not SocketsHttpHandler socketsHttpHandler)
{
throw new InvalidOperationException($"Internals of {nameof(HttpClientHandler)} have changed.");
}
socketsHttpHandler.ConnectTimeout = connectTimeout;
}
}
Usage:
services
.AddHttpClient()
.ConfigureHttpClientDefaults(builder =>
{
builder.ConfigurePrimaryHttpMessageHandler(
() => new CustomHttpClientHandler(TimeSpan.FromSeconds(3))
);
});
EDIT:
With the comments below, that it is possible to use the SocketsHttpHandler
directly as the primary handler, the above can be simplified as:
services
.AddHttpClient()
.ConfigureHttpClientDefaults(builder =>
{
builder.ConfigurePrimaryHttpMessageHandler(
() => new SocketsHttpHandler {
ConnectTimeout = TimeSpan.FromSeconds(3)
}
);
});
This approach is also documented here: https://learn.microsoft.com/en-us/dotnet/core/extensions/httpclient-factory#using-ihttpclientfactory-together-with-socketshttphandler
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With