HttpClient (04.12.2022 3M) Flashcards

Add approaches: 1. Basic usage 2. Use Named Clients 3. Use Generated Clients

1
Q

Why declaring and instantiating HttpClient within a using statement is not preferred?

A

Though this class implements IDisposable, declaring and instantiating it within a using statement is not preferred because when the HttpClient object gets disposed of, the underlying socket is not immediately released, which can lead to a socket exhaustion problem under heavy load. That issue will result in SocketException errors.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

What is intended way of using HttpClient?

A

HttpClient is intended to be instantiated once and reused throughout the life of an application.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

What is the problem of having singletone HttpClient?

A

In a situation where the HttpClient is instantiated as a singleton or a static object, it fails to handle the DNS changes.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

How to avoid issues of socket exhausting and DNS caching?

A

To address the issues mentioned above and to make HttpClient instances manageable, .NET Core 2.1 introduced the IHttpClientFactory interface which can be used to configure and create HttpClient instances in an app through Dependency Injection (DI).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Do issues of socket exhausting and DNS caching relate to HttpClient directly?

A

No. The issues aren’t really with HttpClient per se, but with the default constructor for HttpClient, because it creates a new concrete instance of HttpMessageHandler, which is the one that has sockets exhaustion and DNS changes issues mentioned above.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

What two interfaces are registered while using AddHttpClient()? What is their lifetime?

A

IHttpClientFactory, IHttpMessageHandlerFactory. Both are singletons by default

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

What the purpose of IHttpClientFactory? What methods it contains?

A

A factory abstraction for a component that can create HttpClient instances with a custom configuration for a given logical name.

HttpClient CreateClient(string name)

Creates and configures an HttpClient instance using the configuration that corresponds to the logical name specified by name.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

What the purpose of IHttpMessageHandlerFactory? What methods it contains?

A

A factory abstraction for a component that can create HttpMessageHandler instances with a custom configuration for a given logical name.

HttpMessageHandler CreateHandler(string name);

Creates and configures an HttpMessageHandler instance using the configuration that corresponds to the logical name specified by name.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

What does default IHttpClientFactory realization provide?

A
  1. Provides a central location for naming and configuring logical HttpClient objects. ( given by abstraction of interface IHttpClientFactory)
  2. Manages lifetime of HttpClients and HttpMessageHandlers to avoid socket exhausting and DNS caching.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Name four ways of how you can use IHttpClientFactory in your application?

A
  1. Basic usage
  2. Use Named Clients
  3. Use Typed Clients
  4. Use Generated Clients
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Describe the most simple way to use a typed clients approach. And type clients lifetime.

A
  1. You should create a typed client. The typed client is a class that has injectable HttpClient. For example:

class MyTypedClient
{
MyTypedClient(HttpClient httpClient) {}
}

  1. Register MyTypedClient in DI container:

services.AddHttpClient< MyTypedClient >()

  1. Use TypedClient

public MyController: ControllerBase
{
MyController(MyTypedClient typedClient) {}
}

You can also use interfaces here for example:

class MyTypedClient : IMyTypedClient
{
MyTypedClient (HttpClient httpClient) {}
}

services.AddHttpClient< IMyTypedClient, MyTypedClient >()

public MyController: ControllerBase
{
MyController(IMyTypedClient typedClient) {}
}

Typed clients are registered as transient. HttpClient instance is new for every type client instance (transient too). But HttpMessageHandler is taken from the pool to reduce resource consumption. The lifetime of HttpMessageHandler is managed by pool.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

What is HttpMessageHandlers pool and how handlers are reused? What is lifetime of HttpMessageHandler? Can you configure it?

A

Each time you get an HttpClient object from the IHttpClientFactory, a new instance is returned. But each HttpClient uses an HttpMessageHandler that’s pooled and reused to reduce resource consumption.

The HttpMessageHandler objects in the pool have a lifetime that’s the length of time that an HttpMessageHandler instance in the pool can be reused. The default value is two minutes, but it can be overridden.

HttpMessageHandler objects in the pool are the objects that are reused by MULTIPLE HttpClient instances.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

How to override HttpHandlerMessage lifetime for typed clients?

A

To override it, call SetHandlerLifetime() on the IHttpClientBuilder that’s returned when creating the client, as shown in the following code:

//Set 5 min as the lifetime for the HttpMessageHandler objects in the pool used for the Catalog Typed Client
services.AddHttpClient< CatalogTypedClient >()
.SetHandlerLifetime(TimeSpan.FromMinutes(5));

Each Typed Client can have its own configured handler lifetime value. Set the lifetime to InfiniteTimeSpan to disable handler expiry.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

How you can preconfigure every new HttpClient instance using Typed Client approach?

A

You can do by calling overloading of AddHttpClient method that receives Action< HttpClient > or Action< IServiceProvider, HttpClient > as argument. For example:

services.AddHttpClient(client =>
{
client.BaseAddress = new Uri(Configuration[“BaseUrl”]);
})

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Show how to add Polly policy to HttpClient using Typed Client approach.

A

Policy example:

static IAsyncPolicy GetRetryPolicy()
{
return HttpPolicyExtensions
.HandleTransientHttpError()
.OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
.WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
}

Registration:

services.AddHttpClient< MyTypedClient >()
.AddPolicyHandler(GetRetryPolicy())

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

What is purpose of AddHttpMessageHandler method? Give an example.

A

This method indicates that a client uses a specified implementation of HttpMessageHandler.
A custom message handler must be a descendent of DelegatingHandler

For example:

public class BearerAuthenticationHandler : DelegatingHandler
{
private readonly IIdpTokenClient _idpTokenClient;

    public BearerAuthenticationHandler(IIdpTokenClient idpTokenClient)
    {
        _idpTokenClient = idpTokenClient;
    }

    protected override async Task< HttpResponseMessage > SendAsync(HttpRequestMessage request,
        CancellationToken cancellationToken)
    {
        var token = await _idpTokenClient.GetAccessToken();

        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);

        return await base.SendAsync(request, cancellationToken);
    }
}

services
.AddHttpClient()
.AddHttpMessageHandler< BearerAuthenticationHandler >();

16
Q

What methods DelegatingHandler allows to override?

A
  1. All the object methods
  2. Dispose method
  3. SendAsync method

SendAsync is the most interesting one. It allows doing something before sending a request and after