-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[HttpClientFactory] UseSocketsHttpHandler API naming follow-up #89023
Comments
Tagging subscribers to this area: @dotnet/ncl Issue DetailsWe need to reach consensus on whether we are fine with cc @davidfowl @halter73 @terrajobst @karelz @tekian Context from the discussion on #88864 (comment) ---- @davidfowl wrote: ---- @CarnaViire wrote: Point is, you don't have SocketsHttpHandler in HttpClientFactory by default - you have some PrimaryHandler, so if you'd say ConfigureSocketsHttpHandler, the question is -- where did it come from, so now we're configuring it? So to me, saying UseSocketsHttpHandler was much clearer in explaining what happens - after you call it, the factory would be using SocketsHttpHandler in this named client (and you might decide not to configure it, if you don't specify a delegate) ---- @davidfowl wrote: ---- @CarnaViire wrote:
It's calling ConfigurePrimaryHttpMessageHandler method. "Primary" is an important piece of information in relation to "Configure" verb, as Primary handler is part of HttpClientFactory's "concept", it's a "property" on an HttpClient's configuration. Primary handler property is a "left-hand operand" in the assignment, and SocketsHttpHandler value is a "right-hand operand", so to say. But that's my opinion; I've sent an email to the API review board to discuss this further. ---- @halter73 wrote: services.AddHttpClient("baz")
.ConfigureSocketsHttpHandler(builder =>
builder.Configure(configuration.GetSection("HttpClientSettings:baz"))
.Configure((handler, _) => handler.SslOptions = new SslClientAuthenticationOptions
{
RemoteCertificateValidationCallback = delegate { return true; },
})
); ---- @davidfowl During API review, I thought your feedback would be to have it return the services.AddHttpClient("baz")
.AddSocketsHttpHandler()
.Configure(configuration.GetSection("HttpClientSettings:baz"))
.Configure((handler, _) => handler.SslOptions = new SslClientAuthenticationOptions
{
RemoteCertificateValidationCallback = delegate { return true; },
}); But as @CarnaViire pointed out in API review, this could be annoying if you need the var httpClientBuilder = services.AddHttpClient("baz");
httpClientBuilder.AddSocketsHttpHandler()
.Configure(configuration.GetSection("HttpClientSettings:baz"))
.Configure((handler, _) => handler.SslOptions = new SslClientAuthenticationOptions
{
RemoteCertificateValidationCallback = delegate { return true; },
});
httpClientBuilder.SomethingElseThatReturnsABuilder()
.DoSome()
.MoreThings(); ---- @davidfowl wrote: ---- @CarnaViire wrote: ScopeMismatch fix API could be named Something like ---- @davidfowl wrote: builder.Services.AddHttpClient("Custom")
.RedactLoggedHeaders(header => header.Equals("Authenticaton", StringComparison.OrdinalIgnoreCase))
.ConfigureHttpClient(client => client.Timeout = TimeSpan.FromSeconds(10))
.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler()
{
AutomaticDecompression = System.Net.DecompressionMethods.GZip
})
.SetHandlerLifetime(TimeSpan.FromMinutes(5))
.AddHttpMessageHandler<AuthenticationHander>(); You're suggesting we replace Set* with Use* because we're setting a property that is being configured (even that that's all configure* methods do right?), but because there's no arguments (or because it's optional). After this change, it'll look like this: builder.Services.AddHttpClient("Custom")
.RedactLoggedHeaders(header => header.Equals("Authenticaton", StringComparison.OrdinalIgnoreCase))
.ConfigureHttpClient(client => client.Timeout = TimeSpan.FromSeconds(10))
.UseSocketsHttpHandler(h =>
{
h.PooledConnectionLifetime = TimeSpan.FromMinutes(5);
})
.SetHandlerLifetime(TimeSpan.FromMinutes(5))
.AddHttpMessageHandler<AuthenticationHander>(); ---- @CarnaViire wrote:
"obj.SetProperty(value)" translates into "obj.Property = value", doesn't it? If we choose Set* for the API, you would get "obj.value??? = ???" instead.... It's the same logical error IMHO as with Configure* I'm not married to Use* in particular, I just believe Set*, Configure* and Add* are all logically wrong here..... BTW doesn't ASP.NET have ---- @davidfowl wrote:
|
Sounds pretty consistent to me 🙂 Also, interesting comparison, as there's |
Expanding a little bit re If HttpClientFactory either
-- in these two cases I would be fine with |
@davidfowl @halter73 any thoughts on this? |
We are past the time we can make API changes for 8.0. cc @davidfowl |
We need to reach consensus on whether we are fine with
UseSocketsHttpHandler
name for API introduced by #84075, or we want to rename it toConfigure*
orSet*
or something else.My opinion is that
Configure*
/Add*
/Set*
are logically wrong; my explanations are under the cut below. Also,Use*
patern is very similar in core meaning to what ASP.NET Core uses inUseKestrel
,UseHttpSys
etc.cc @davidfowl @halter73 @terrajobst @karelz @tekian
Explanation on why I chose not to use Configure/Add/Set in API name
1. ConfigureSocketsHttpHandler
I honestly believe such naming is confusing. HttpClientFactory doesn't have a concept of "SocketsHttpHandler" as a property that could be changed/configured. It has "Primary handler" and "Additional handlers" concepts. So you change/configure Primary handler, not "SocketsHttpHandler". Where did SocketsHttpHandler come from so we are configuring it? The name would look even stranger given that it is possible to not change anything in SocketsHttpHandler instance (by not passing a delegate):
2. ConfigurePrimarySocketsHttpHandler
This is tiny bit better, as it contains the word "Primary", which hints that it is Named HttpClient's Primary handler that is being configured. However, now the naming is IMHO too similar to the existing ConfigurePrimaryHttpMessageHandler -- both start with "ConfigurePrimary...", end with "...Handler", contain "Http"... It is not end of the world, but you still need to make some effort to differentiate the two. And it still looks a bit strange if it's used without passing a delegate.
3. AddSocketsHttpHandler
While this is a decent alternative, IMHO, Add should only be used with collection-related things. If we add the handler, what is happening with the old one? is it staying? both will be called? 🙂
4. SetSocketsHttpHandler
This suffers from the same problem the first alternative had. We are setting Primary handler, not "SocketsHttpHandler".
Context from the discussion on #88864
@davidfowl wrote:
@CarnaViire wrote:
@davidfowl wrote:
@CarnaViire wrote:
@halter73 wrote:
@davidfowl wrote:
@CarnaViire wrote:
@davidfowl wrote:
@CarnaViire wrote:
@davidfowl wrote:
The text was updated successfully, but these errors were encountered: