Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Static HttpClient thread safe on ASP.net HttpRequest

We are creating a wrapper for HttpClient. As we are going to follow performance optimization guidance from https://github.com/mspnp/performance-optimization. We want to avoid anti-pattern - Improper instantiation mentioned in that document. I referred this guidance to my team to use static HttpClient. The feedback I have got is on thread-safety. Each request has a header containing user claim. Since I have a static HttpClient, will it be thread-safe? If we have multiple requests hitting the code (for example GET) at the same time, will it be a race condition to set header? We have implementation as below.

public class HttpClientHelper{
private static readonly HttpClient _HttpClient;
static HttpClientHelper() {
        HttpClient = new HttpClient();
        HttpClient.Timeout = TimeSpan.FromMinutes(SOME_CONFIG_VALUE);
}

public async Task<HttpResponseMessage> CallHttpClientPostAsync(string requestUri, HttpContent requestBody)
{
    AddHttpRequestHeader(httpClient);
    var response = await httpClient.PostAsync(requestUri, requestBody); //Potential thread synchronization issue???
    return response;
}

public HttpResponseMessage CallHttpClientGet(string requestUri)
{
    AddHttpRequestHeader(httpClient);
    var response = httpClient.GetAsync(requestUri).Result; //Potential thread synchronization issue???
    return response;
}

private void AddHttpRequestHeader(HttpClient client)
{
    string HeaderName = "CorrelationId";
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(Properties.Settings.Default.HttpClientAuthHeaderScheme, GetTokenFromClaims()); //Race condition???
    if (client.DefaultRequestHeaders.Contains(HeaderName))
        client.DefaultRequestHeaders.Remove(HeaderName);
    client.DefaultRequestHeaders.Add(HeaderName, Trace.CorrelationManager.ActivityId.ToString());
}

}

like image 318
sadhat75 Avatar asked Apr 21 '15 03:04

sadhat75


People also ask

Is a static HttpClient thread-safe?

But HttpClient is different. Although it implements the IDisposable interface it is actually a shared object. This means that under the covers it is reentrant and thread safe.

Is DefaultRequestHeaders thread-safe?

It would be good to add a note that changing BaseAddress or DefaultRequestHeaders is not a thread-safe operation, and you should change them on concurrent requests.

In which of the following types of applications we can use HttpClient?

HttpClient is used to send an HTTP request, using a URL. HttpClient can be used to make Web API requests from the console Application, Winform Application, Web form Application, Windows store Application, etc.

Why do we need HttpClient in C#?

The HttpClient class instance acts as a session to send HTTP requests. An HttpClient instance is a collection of settings applied to all requests executed by that instance. In addition, every HttpClient instance uses its own connection pool, isolating its requests from requests executed by other HttpClient instances.


1 Answers

Your team is correct, this is far from thread safe. Consider this scenario:

  • Thread A sets CorrelationId header to "foo".
  • Thread B sets CorrelationId header to "bar".
  • Thread A sends request, which contains thread B's CorrelationId.

A better approach would be for your CallXXX methods to create new HttpRequestMessage objects, and set the header on those, and use HttpClient.SendAsync to make the call.

Keep in mind also that re-using HttpClient instances is only beneficial if you're making multiple calls to the same host.

like image 181
Todd Menier Avatar answered Sep 23 '22 22:09

Todd Menier