Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use HttpClientHandler with HttpClientFactory in .NET Core

I want to use the HttpClientFactory that is available in .NET Core 2.1 but I also want to use the HttpClientHandler to utilize the AutomaticDecompression property when creating HttpClients.

I am struggling because the .AddHttpMessageHandler<> takes a DelegatingHandler not a HttpClientHandler.

Does anyone know how to get this to work?

Thanks, Jim

like image 885
Jim Fritchman Avatar asked Jun 07 '18 18:06

Jim Fritchman


People also ask

How do I use HttpClientHandler with Ihttpclientfactory?

In general, HttpClientHandler can be used to configure a specific configuration like custom policy, headers, or security mechanism, compression, certificates, etc. We shall cover the below aspects in this article, Configure HttpClientHandler for Authentication Example: Bearer or Basic.

What is HttpClientFactory in C#?

Not only that HttpClientFactory can create and manage new HttpClient instances but also, it works with underlying handlers. Basically, when creating new HttpClient instances, it doesn't recreate a new message handler but it takes one from a pool. Then, it uses that message handler to send the requests to the API.

What are the differences between HttpClientFactory and HttpClient?

It has a method CreateClient which returns the HttpClient Object. But in reality, HttpClient is just a wrapper, for HttpMessageHandler. HttpClientFactory manages the lifetime of HttpMessageHandelr, which is actually a HttpClientHandler who does the real work under the hood.

Is HttpClientFactory thread safe?

HttpClient is a mutable object but as long as you are not mutating it, it is actually thread safe and can be shared.


2 Answers

More properly to define primary HttpMessageHandler via ConfigurePrimaryHttpMessageHandler() method of HttpClientBuilder. See example below to configure typed client how.

services.AddHttpClient<TypedClient>()     .ConfigureHttpClient((sp, httpClient) =>     {         var options = sp.GetRequiredService<IOptions<SomeOptions>>().Value;         httpClient.BaseAddress = options.Url;         httpClient.Timeout = options.RequestTimeout;     })     .SetHandlerLifetime(TimeSpan.FromMinutes(5))     .ConfigurePrimaryHttpMessageHandler(x => new HttpClientHandler()      {         AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;     })     .AddHttpMessageHandler(sp => sp.GetService<SomeCustomHandler>().CreateAuthHandler())     .AddPolicyHandlerFromRegistry(PollyPolicyName.HttpRetry)     .AddPolicyHandlerFromRegistry(PollyPolicyName.HttpCircuitBreaker); 

Also you can define error handling policy via usage of special builders methods of Polly library. In this example policy should be predefined and stored into policy registry service.

public static IServiceCollection AddPollyPolicies(     this IServiceCollection services,      Action<PollyPoliciesOptions> setupAction = null) {     var policyOptions = new PollyPoliciesOptions();     setupAction?.Invoke(policyOptions);      var policyRegistry = services.AddPolicyRegistry();      policyRegistry.Add(         PollyPolicyName.HttpRetry,         HttpPolicyExtensions             .HandleTransientHttpError()             .WaitAndRetryAsync(                 policyOptions.HttpRetry.Count,                 retryAttempt => TimeSpan.FromSeconds(Math.Pow(policyOptions.HttpRetry.BackoffPower, retryAttempt))));      policyRegistry.Add(         PollyPolicyName.HttpCircuitBreaker,         HttpPolicyExtensions             .HandleTransientHttpError()             .CircuitBreakerAsync(                 handledEventsAllowedBeforeBreaking: policyOptions.HttpCircuitBreaker.ExceptionsAllowedBeforeBreaking,                     durationOfBreak: policyOptions.HttpCircuitBreaker.DurationOfBreak));      return services; } 
like image 101
trueboroda Avatar answered Sep 21 '22 18:09

trueboroda


Actually I'm not using automatic decompression but the way to achieve this is to properly register http client

services.AddHttpClient<MyCustomHttpClient>()    .ConfigureHttpMessageHandlerBuilder((c) =>      new HttpClientHandler()      {         AutomaticDecompression = System.Net.DecompressionMethods.GZip      }    )    .AddHttpMessageHandler((s) => s.GetService<MyCustomDelegatingHandler>()) 
like image 24
djaszczurowski Avatar answered Sep 21 '22 18:09

djaszczurowski