Alex Gordon
Alex Gordon

Reputation: 60751

how to use a static instance of HttpClient with multiple consumers

How do we reuse a static instance of HttpClient?

I have a static HttpClient that I would like to reuse concurrently:

    private static HttpClient client = new HttpClient();

I'm creating my request like so:

            var attachTopic = GetEnvironmentVariable("Attach:EventTopicUri");
            var attachTopicKey = GetEnvironmentVariable("Attach:EventTopicKey");
            client.BaseAddress = new Uri(attachTopic);
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Add("aeg-sas-key", attachTopicKey);

And then posting the request:

await client.PostAsJsonAsync("", new[] { /*some awesome object*/ });

However, I'm getting the following issue:

etc

How do we make concurrent requests with the same header information on a static HttpClient?

Upvotes: 0

Views: 3830

Answers (1)

Alex Pshul
Alex Pshul

Reputation: 702

I suggest you introduce dependency injection to your project. You can see the oficial docs HERE.

The first example in the docs adds HttpClient to the service provider:

public override void Configure(IFunctionsHostBuilder builder)
{
    builder.Services.AddHttpClient();
    builder.Services.AddSingleton((s) => {
        return new CosmosClient(Environment.GetEnvironmentVariable("COSMOSDB_CONNECTIONSTRING"));
    });
    builder.Services.AddSingleton<ILoggerProvider, MyLoggerProvider>();
}

To use your HttpClient, you'll have to inject it to your functions class constructor:

public class MyFunc
{
    private readonly HttpClient _client;

    public MyFunc(IHttpClientFactory httpClientFactory)
    {
        _client = httpClientFactory.CreateClient();
    }

    [FunctionName("DoSomething")]
    public async Task<IActionResult> Get(
        [HttpTrigger(AuthorizationLevel.Function, "get", Route = "do-something")] HttpRequest req,
        ILogger log)
    {
        log.LogInformation("C# HTTP trigger function processed a request.");
        var res = await _client.GetAsync("my-cool-url.com);

        return new OkResult(res);
   }
}

What I especially like about this approach, is that you can create different keyed clients when you register it to the DI:

private void ConfigureService(IWebJobBuilder builder)
{
    // Some logic
    builder.Services.AddHttpClient("aaa", client =>
    {
        client.BaseAddress = new Uri("base-address.com");
    });
}

And then use it like this:

public MyFunc(IHttpClientFactory httpClientFactory)
{
    _client = httpClientFactory.CreateClient("aaa");
}

Let me know if something isn't working for you. :)

Upvotes: 1

Related Questions