Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IHttpClientFactory and changing the base HttpClient.BaseAddress

What is the best practice for IHttpClientFactory and changing HttpClient.BaseAddress?

When creating my Dependency Injection I am doing it like this:

services.AddHttpClient("MyApp", c =>
    {
        c.BaseAddress = new Uri("https://myurl/");
        c.DefaultRequestHeaders.Add("Accept", "application/json");
    }).ConfigurePrimaryHttpMessageHandler(handler => new HttpClientHandler()
    { AutomaticDecompression = DecompressionMethods.GZip });

Then when I need an HttpClient doing this:

var client = clientFactory.CreateClient("MyApp");

This works great, but there are times, during runtime that the BaseAddress needs to change. During the run I am not able to change the BaseAddress after it has been injected. Now I could ignore BaseAddress altogether and just send the entire address in the API call, however, I do not know if this is the correct way of doing it. Something like this:

await using var stream = await client.GetStreamAsync($"{addresss}/{api}");
using var streamReader = new StreamReader(stream);
using var textReader = new JsonTextReader(streamReader);
var serializer = new JsonSerializer();
data = serializer.Deserialize<List<T>>(textReader);
like image 279
Xaphann Avatar asked Jan 26 '23 00:01

Xaphann


1 Answers

there are times, during runtime that the BaseAddress needs to change. During the run I am not able to change the BaseAddress after it has been injected.

BaseAddress can be changed up until the first request is sent. At that point, it is locked down and cannot be changed again. The HttpClient factory pattern assumes that each injected client has only one BaseAddress (which may be unset).

Now I could ignore BaseAddress altogether and just send the entire address in the API call, however, I do not know if this is the correct way of doing it.

Your options are:

  1. Define multiple clients, one for each BaseAddress. This is the normal approach if you have a few well-known hosts.
  2. Define a single client and do not use BaseAddress, passing the entire url in each call. This is perfectly permissible.
  3. Define your own factory type that uses IHttpClientFactory to pass out HttpClient instances where each instance can specify its own BaseAddress. I would only use this more complex approach if you had some code that required a BaseAddress (e.g., Refit) but needed to use it with a dynamic host.
like image 94
Stephen Cleary Avatar answered Jan 27 '23 14:01

Stephen Cleary