Skip to content

Conversation

WhitWaldo
Copy link
Contributor

Description

As a best practice, it's a good idea to create all HttpClient instances from an IHttpClientFactory for the reasons listed here. Today's version of Dapr doesn't do this across any of the packages, with the exception of sort of doing this in Dapr.Workflow.

Because we use a factory approach to creating the DaprClient itself that exposes methods for specifying the Dapr API token, declaring the timeout value or specifying the gRPC/HTTP endpoints, among other options, we lack any functionality that might be exposed to the user to do a more elaborate configuration of the HttpClient that's produced.

At the same time, I hesitate to simply apply a global configuration against an IHttpClientFactory as it would apply to all clients. One aspect of how I've built out Dapr DI so far is to enable the developer to point to different endpoints to use different aspects of Dapr (e.g. use the sidecar to instantiate a DaprClient for state management, but point to Diagrid's Catalyst platform to process workflow operations). Having a global configuration against the IHttpClientFactory would negate this capability as one settings configuration would rein over all implementations.

The compromise made here is to support an IDaprHttpClientFactory. When the developer registers Dapr using AddDaprClient() or indirectly does the same by calling any of the various AddDapr*() methods in each of the packages (which generally all take a dependency on AddDaprClient() as well), this also registers the IDaprHttpClientFactory which accepts the same Action<IServiceProvider, HttpClient> parameter that the AddHttpClient() accepts, allowing the user to apply a custom configuration to the client. The client they're modifying will have already been updated with the Dapr configuration, so any custom configuration will take precedence over this setup, but the option is then there for developers to take advantage of.

Should said developer wish to have an instance of the HttpClient for their own purposes, merely inject IDaprHttpClientFactory into their type and use the returned HttpClient from the CreateClient() method.

This implementation is provided as a proof-of-concept of the latest generation of this idea and needs both best practice documentation and unit testing before it should be merged.

Issue reference

We strive to have all PR being opened based on an issue, where the problem or feature have been discussed prior to implementation.

Please reference the issue this PR will close: #1484

Checklist

Please make sure you've completed the relevant tasks for this PR, out of the following list:

  • Code compiles correctly
  • Created/updated tests
  • Extended the documentation

@WhitWaldo WhitWaldo added this to the v1.17 milestone Aug 22, 2025
@WhitWaldo WhitWaldo self-assigned this Aug 22, 2025
@WhitWaldo WhitWaldo requested a review from a team as a code owner August 22, 2025 05:40
@WhitWaldo WhitWaldo added the kind/enhancement New feature or request label Aug 22, 2025
@WhitWaldo WhitWaldo requested a review from a team as a code owner August 22, 2025 05:40
@atrauzzi
Copy link

My understanding is if we referred to the framework norms, and allowed named and typed registrations, we would get away from the limitation of only being able to globally configure one HttpClient.

This would allow people to have different configurations the way you want by setting each variant up in DI.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

HttpClient quality of life
2 participants