Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Re-use HttpClient instance with different credentials per request

I have an MVC 5 application that includes a controller action that makes a HTTP request. To do this, I am using HttpClient.

I have learnt from others (like this blog post) and from my own experiences as well that instantating numerous HttpClients simultaneously can have a negative effect on the performance of not just the application but the server as a whole.

So far my requirements of reusing a HttpClient instance could be solved by code like this

using (var handler = new HttpClientHandler() { Credentials = new NetworkCredential(getUsername(), getHashedPassword())})
using (var client = new HttpClient(handler))
{
   // Long running loop that makes a different HTTP request
   // on each iteration but using the same HttpClient instance
}

Requiring similar re-use in a controller action, I elected to use a static instance of HttpClient in the controller class. The problem is that the credentials passed to the HttpClientHandler change with each request since they partially depend on a timestamp value(the getHashedPassword() method produces a different password each time it is called).

Because of the way authentication is carried out on the remote server, I have to include the password in the XML content that forms the body of the request as well.

And this is where I run into the problem:

How can I re-use the same HttpClient instance across different calls to the controller action while making sure it is using a handler with up to date credentials?

Is it even possible to do this?

Is it possible to update the handler after passing it to the HttpInstance?

Or would I need to modify the client object's DefaultRequestHeaders which according to some sources may introduce subtle bugs if the object is used concurrently by different threads?

like image 891
Steve S Avatar asked Mar 17 '26 08:03

Steve S


2 Answers

Instead of using HTTPClient directly, it is advised to create a client instance using HTTPClientFactory. Once done, you can create named clients which can be reused based on your handlers. Here is a useful link on the same.

If you want to further optimize your code, you can maintain a concurrent dictionary.

private readonly ConcurrentDictionary<string, HTTPClient> _clientMap = new ConcurrentDictionary<string, HTTPClient>();

This can then be leveraged like this:

using(var client = _clientMap.GetOrAdd($"{handlerName}", _clientFactory.CreateClient("handlerName"));

In the above snippet, _clientFactory refers to IHttpClientFactory instance.

like image 59
Rohith Nandan Avatar answered Mar 19 '26 22:03

Rohith Nandan


The HttpClientHandler object is a component that handles requests used by the HttpClient. You want to update the HttpClientHandler for every request that requires new credentials. There are several ways to do this. You can set up-to-date credentials by creating a new HttpClientHandler instance before each request.

using (var handler = new HttpClientHandler())
    using (var client = new HttpClient(handler))
    {
       handler.Credentials = new NetworkCredential(getUsername(), getHashedPassword());
       // HttpClient örneğini kullanarak istekleri gerçekleştirin
    }

By updating the DefaultRequestHeaders you can pass new credentials on every request.

using (var handler = new HttpClientHandler())
using (var client = new HttpClient(handler))
{
   client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes($"{getUsername()}:{getHashedPassword()}")));
   // HttpClient örneğini kullanarak istekleri gerçekleştirin
}
like image 21
Mustafa Alp Yanıkoğlu Avatar answered Mar 19 '26 23:03

Mustafa Alp Yanıkoğlu