[ ] Regression (a behavior that stopped working in a new release)
[ ] Bug report
[ ] Performance issue
[ X] Documentation issue or request
Current behavior
In Squidex.ClientLibrary.SquidexOptions you provide the option to override IHttpClientFactory, which is a custom interface [Squidex.ClientLibrary.Configuration]
It also adds support for typed client to the di container like serviceClient.AddHttpClient()
Due to the client factory we get goodies like logging, retry, backoff etc.
My question for you is wether we can use the Microsoft variant of the interface, or if you have a working version of your interface that loops it to the microsoft one.
Shameless self promotion here, https://kaylumah.nl/2021/05/23/generate-csharp-client-for-openapi.html
have some experience with NSwag, I think the default here is that HttpClient gets injected via the constructor. Thus as I mention in the closing thoughts it works out ot the box via the model (need to do a write up on that still)
So, where do we go from here? I did not mention it in the article, but in every generated client, we need to inject System.Net.HttpClient , which means we can combine it with HttpClientFactory and all the options it provides. Alas, that is also a topic for another day.
/// <inheritdoc />
public HttpClient CreateHttpClient(bool appendApi = true)
{
Uri baseUri = new Uri(this.Options.Url, UriKind.Absolute);
if (appendApi)
baseUri = new Uri(baseUri, "api/");
HttpMessageHandler httpMessageHandler = this.CreateHttpMessageHandler();
HttpClient httpClient = this.Options.ClientFactory.CreateHttpClient(httpMessageHandler) ?? new HttpClient(httpMessageHandler, false);
httpClient.BaseAddress = baseUri;
httpClient.Timeout = this.Options.HttpClientTimeout;
this.Options.Configurator.Configure(httpClient);
return httpClient;
}
private HttpMessageHandler CreateHttpMessageHandler()
{
HttpClientHandler httpClientHandler = new HttpClientHandler();
this.Options.Configurator.Configure(httpClientHandler);
AuthenticatingHttpMessageHandler httpMessageHandler = new AuthenticatingHttpMessageHandler(this.Options.Authenticator);
httpMessageHandler.InnerHandler = (HttpMessageHandler) httpClientHandler;
HttpMessageHandler inner = (HttpMessageHandler) httpMessageHandler;
return this.Options.ClientFactory.CreateHttpMessageHandler(inner) ?? inner;
}
If I can get AuthenticationgHttpMessageHandler to play nice with https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-6.0#outgoing-request-middleware I think I can make it work.
That was fast
If I understand your design correctly I need to implement IHttpClientProvider to use the microsoft thingy and then configure authentication etc?
Yes, I would like to add authentication by default, but I am not sure if it a good idea, because the order of the message handlers really matter and I don’t want to destroy that.
I have created a second project for the integration to IServiceCollection:
So if you can AddSquidexClient yourself you can make all customizations yourself.
It would be great if you can test that: Just clone the code and then add a reference to the project itself. Then you can easily make fixes if you find issues.
I validated your solution and everything appears to be working as expected.
I have tried both manually creating ISquidexClientManager and using the extension methods.
For the manual one I used the new HttpClientProvider and the default StaticHttpClientProvider. The former I get logging like “Sending HTTP request GET …”, the latter I get no logging just as before.
HttpClientProvider is internal, so if I want to deviate from the default AddSquidex (say for example a custom factory with additional logging or polly) I also need a own HttpClientProvider
Not clear to me what HttpClientProvider.Return() is meant to do since it disposes the client?
SquidexClientLibraryServiceExtensions line 33 could use a Action<SquidexServiceOptions>? configure = null
I think AddSquidexClient could be split into two methods, one where the main client is configured and one that adds all the typed client like services.AddSingleton(
c => c.GetRequiredService().CreateAppsClient()); that way if I choose to do a custom registration of ISquidexClientManager I still get the reusable register client method
Also just noticed, Authenticator : IAuthenticator uses the old squidex clientfactory,
so there logging would still be missing. But not sure if that is an issue, or if there are other places that should now use the ClientProvider instead of the ClientFactory