Description
Is your feature request related to a problem? Please describe.
My application needs runtime-defined named HttpClient
configuration, and I'm using IHttpClientFactory
. My application also needs to configure different DelegatingHandler
chains unique to each named configuration (for injecting configuration-specific Bearer tokens and access_token
refresh logic).
My application is a headless Windows service that stores 1...N-many named HttpClient
configurations on-disk and it uses an injected-service to read the stored configurations, so the IServiceProvider
isn't available to read the configuration while it's still calling IServiceCollection.AddHttpClient<MyClient>( ... )
(and the idea of maintaining multiple root IServiceProvider
instances isn't appealing either).
Ostensibly, the IHttpClientFactory
requires all named HttpClient
s to be set-up during service-configuration - which would make it unsuitable for my application - however I noticed that DefaultHttpClientFactory
's pool of HttpMessageHandler
instances can be added-to even after configuration has completed - this does not seem to be documented either way - so I'm not sure if it's a bug (i.e. it should be immutable) or a feature (for runtime-configured HttpClient
and HttpMessageHandlerBuilder
instances).
Describe the solution you'd like
- A statement from the PM responsible declaring the immutability of
IHttpClient
's configuration. - If it is immutable, then fix the bug.
- If it's mutable, then make it easier to add dynamic configuration of
HttpClient
without jumping through hoops withIConfigureNamedOptions
.
Describe alternatives you've considered
Right now my application depends on the current behaviour for dynamic HttpClient
configuration, like so:
internal class DynamicHttpClientFactoryConfiguration : IConfigureNamedOptions<HttpClientFactoryOptions>
{
public void Configure( String httpClientName, HttpClientFactoryOptions options )
{
IAccessTokenRenewerFactoryStore store = this.sp.GetRequiredService<IAccessTokenRenewerFactoryStore>();
if( store.TryGetConfiguration( httpClientName: httpClientName, out MyHttpClientConfiguration cfg, out AccessTokenRenewer atr ) )
{
options.HttpClientActions.Add( httpClient =>
{
httpClient.BaseAddress = cfg.Authority;
} );
options.HttpMessageHandlerBuilderActions.Add( httpMessageHandlerBuilder =>
{
AccessTokenRenewDelegatingHandler delegatingHandler = new AccessTokenRenewDelegatingHandler( atr );
httpMessageHandlerBuilder.AdditionalHandlers.Add( delegatingHandler );
} );
}
}
}
And it "just works" whenever code anywhere in my project calls IHttpClientFactory.CreateClient( configurationName )
(provided that configurationName
exists in my IAccessTokenRenewerFactoryStore
).