-
Notifications
You must be signed in to change notification settings - Fork 6.1k
Networking breaking changes #43351
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
Merged
Merged
Networking breaking changes #43351
Changes from 6 commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
3f7b97b
query redaction
gewarren bfc427c
server.port metrics
gewarren 759e9da
primary handler
gewarren 2fee7e0
remove metadata
gewarren 841ac12
Uri -> URI
gewarren 845f7f2
undo casing change
gewarren 8a1012e
Update docs/core/compatibility/networking/9.0/server-port-attribute.md
gewarren 92e5948
Merge branch 'main' into networking-bc
gewarren File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,95 @@ | ||
| --- | ||
| title: "HttpClientFactory uses SocketsHttpHandler as primary handler" | ||
| description: Learn about the breaking change in networking in .NET 9 where HttpClientFactory now uses SocketsHttpHandler as the default primary handler. | ||
| ms.date: 11/5/2024 | ||
| --- | ||
|
|
||
| # HttpClientFactory uses SocketsHttpHandler as primary handler | ||
|
|
||
| `HttpClientFactory` allows you to configure an <xref:System.Net.Http.HttpMessageHandler> pipeline for named and typed <xref:System.Net.Http.HttpClient> objects. The inner-most handler, or the one that actually sends the request on the wire, is called a *primary handler*. If not configured, this handler was previously always an <xref:System.Net.Http.HttpClientHandler>. While the default primary handler is an implementation detail, there were users who depended on it. For example, some users cast the primary handler to `HttpClientHandler` to set properties like <xref:System.Net.Http.HttpClientHandler.ClientCertificates>, <xref:System.Net.Http.HttpClientHandler.UseCookies>, and <xref:System.Net.Http.HttpClientHandler.UseProxy>. | ||
|
|
||
| With this change, the default primary handler is a <xref:System.Net.Http.SocketsHttpHandler> on platforms that support it. On other platforms, for example, .NET Framework, <xref:System.Net.Http.HttpClientHandler> continues to be used. | ||
|
|
||
| `SocketsHttpHandler` now also has the <xref:System.Net.Http.SocketsHttpHandler.PooledConnectionLifetime> property preset to match the <xref:Microsoft.Extensions.Http.HttpClientFactoryOptions.HandlerLifetime> value. (It reflects the latest value, if `HandlerLifetime` was configured by the user). | ||
|
|
||
| ## Version introduced | ||
|
|
||
| .NET 9 Preview 6 | ||
|
|
||
| ## Previous behavior | ||
|
|
||
| The default primary handler was `HttpClientHandler`. Casting it to `HttpClientHandler` to update the properties happened to work. | ||
|
|
||
| ```csharp | ||
| services.AddHttpClient("test") | ||
| .ConfigurePrimaryHttpMessageHandler((h, _) => | ||
| { | ||
| ((HttpClientHandler)h).UseCookies = false; | ||
| }); | ||
|
|
||
| // This worked. | ||
| var client = httpClientFactory.CreateClient("test"); | ||
| ``` | ||
|
|
||
| ## New behavior | ||
|
|
||
| On platforms where `SocketsHttpHandler` is supported, the default primary handler is now `SocketsHttpHandler` with `PooledConnectionLifetime` set to the `HandlerLifetime` value. Casting it to `HttpClientHandler` to update the properties throws an <xref:System.InvalidCastException>. | ||
|
|
||
| For example, the same code from the [Previous behavior](#previous-behavior) section now throws an <xref:System.InvalidCastException>: | ||
|
|
||
| > System.InvalidCastException: Unable to cast object of type 'System.Net.Http.SocketsHttpHandler' to type 'System.Net.Http.HttpClientHandler'. | ||
|
|
||
| ## Type of breaking change | ||
|
|
||
| This change is a [behavioral change](../../categories.md#behavioral-change). | ||
|
|
||
| ## Reason for change | ||
|
|
||
| One of the most common problems `HttpClientFactory` users run into is when a `Named` or `Typed` client erroneously gets captured in a singleton service, or, in general, stored somewhere for a period of time that's longer than the specified <xref:Microsoft.Extensions.Http.HttpClientFactoryOptions.HandlerLifetime>. Because `HttpClientFactory` can't rotate such handlers, they might end up not respecting DNS changes. | ||
|
|
||
| This problem can be mitigated by using <xref:System.Net.Http.SocketsHttpHandler>, which has an option to control <xref:System.Net.Http.SocketsHttpHandler.PooledConnectionLifetime>. Similarly to <xref:Microsoft.Extensions.Http.HttpClientFactoryOptions.HandlerLifetime>, the pooled connection lifetime allows regularly recreating connections to pick up DNS changes, but on a lower level. A client with `PooledConnectionLifetime` set up can be safely used as a singleton. | ||
|
|
||
| It is, unfortunately, easy and seemingly "intuitive" to inject a `Typed` client into a singleton. But it's hard to have any kind of check or analyzer to make sure `HttpClient` isn't captured when it wasn't supposed to be captured. It's also hard to troubleshoot the resulting issues. So as a preventative measure—to minimize the potential impact of erroneous usage patterns—the `SocketsHttpHandler` mitigation is now applied by default. | ||
|
|
||
| This change only affects cases when the client wasn't configured by the end user to use a custom <xref:Microsoft.Extensions.Http.HttpMessageHandlerBuilder.PrimaryHandler> (for example, via <xref:Microsoft.Extensions.DependencyInjection.HttpClientBuilderExtensions.ConfigurePrimaryHttpMessageHandler``1(Microsoft.Extensions.DependencyInjection.IHttpClientBuilder)>). | ||
|
|
||
| ## Recommended action | ||
|
|
||
| There are three options to work around the breaking change: | ||
|
|
||
| - Explicitly specify and configure a primary handler for each of your clients: | ||
|
|
||
| ```csharp | ||
| services.AddHttpClient("test") | ||
| .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler() { UseCookies = false }); | ||
| ``` | ||
|
|
||
| - Overwrite the default primary handler for all clients using <xref:Microsoft.Extensions.DependencyInjection.HttpClientFactoryServiceCollectionExtensions.ConfigureHttpClientDefaults(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Action{Microsoft.Extensions.DependencyInjection.IHttpClientBuilder})>: | ||
|
|
||
| ```csharp | ||
| services.ConfigureHttpClientDefaults(b => | ||
| b.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler() { UseCookies = false })); | ||
| ``` | ||
|
|
||
| - In the configuration action, check for both `HttpClientHandler` and `SocketsHttpHandler`: | ||
|
|
||
| ```csharp | ||
| services.AddHttpClient("test") | ||
| .ConfigurePrimaryHttpMessageHandler((h, _) => | ||
| { | ||
| if (h is HttpClientHandler hch) | ||
| { | ||
| hch.UseCookies = false; | ||
| } | ||
|
|
||
| if (h is SocketsHttpHandler shh) | ||
| { | ||
| shh.UseCookies = false; | ||
| } | ||
| }); | ||
| ``` | ||
|
|
||
| ## Affected APIs | ||
|
|
||
| - <xref:Microsoft.Extensions.Http.HttpMessageHandlerBuilder.PrimaryHandler?displayProperty=fullName> | ||
| - <xref:Microsoft.Extensions.DependencyInjection.HttpClientBuilderExtensions.ConfigurePrimaryHttpMessageHandler(Microsoft.Extensions.DependencyInjection.IHttpClientBuilder,System.Action{System.Net.Http.HttpMessageHandler,System.IServiceProvider})?displayProperty=fullName> |
68 changes: 68 additions & 0 deletions
68
docs/core/compatibility/networking/9.0/query-redaction-events.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| --- | ||
| title: "URI query redaction in HttpClient EventSource events" | ||
| description: "Learn about the breaking change in networking in .NET 9 where HttpClient EventSource events scrub query strings by default to enhance privacy." | ||
| ms.date: 11/5/2024 | ||
| ai-usage: ai-assisted | ||
| --- | ||
|
|
||
| # URI query redaction in HttpClient EventSource events | ||
|
|
||
| In .NET 9, the default behavior of <xref:System.Diagnostics.Tracing.EventSource> events emitted by <xref:System.Net.Http.HttpClient> and <xref:System.Net.Http.SocketsHttpHandler> (`EventSource` name: `System.Net.Http`) has been modified to scrub query strings. This change enhances privacy by preventing the logging of potentially sensitive information contained in query strings. If necessary, you can override this behavior. | ||
|
|
||
| ## Version introduced | ||
|
|
||
| .NET 9 Preview 7 | ||
|
|
||
| ## Previous behavior | ||
|
|
||
| Previously, events emitted by `HttpClient` and `SocketsHttpHandler` included query string information, which could inadvertently expose sensitive information. | ||
|
|
||
| ## New behavior | ||
|
|
||
| With the change in [dotnet/runtime#104741](https://github.com/dotnet/runtime/pull/104741), query strings are replaced by a `*` character in `HttpClient` and `SocketsHttpHandler` events, by default. This change affects specific events and parameters such as `pathAndQuery` in `RequestStart` and `redirectUri` in `Redirect`. | ||
|
|
||
| ## Type of breaking change | ||
|
|
||
| This change is a [behavioral change](../../categories.md#behavioral-change). | ||
|
|
||
| ## Reason for change | ||
|
|
||
| The primary reason for this change was to enhance privacy by reducing the risk of sensitive information being logged inadvertently. Query strings often contain sensitive data, and redacting them from logs by default helps protect this information. | ||
|
|
||
| ## Recommended action | ||
|
|
||
| If you need query string information when consuming `HttpClient` or `SocketsHttpHandler` events and you're confident that it's safe to do so, you can enable query string logging globally by setting an AppContext switch in one of three ways: | ||
|
|
||
| - In the project file. | ||
|
|
||
| ```xml | ||
| <ItemGroup> | ||
| <RuntimeHostConfigurationOption Include="System.Net.Http.DisableUriRedaction" Value="true" /> | ||
| </ItemGroup> | ||
| ``` | ||
|
|
||
| - In the *runtimeconfig.json* file. | ||
|
|
||
| ```json | ||
| { | ||
| "runtimeOptions": { | ||
| "configProperties": { | ||
| "System.Net.Http.DisableUriRedaction": true | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| - Through an environment variable. | ||
|
|
||
| Set `DOTNET_SYSTEM_NET_HTTP_DISABLEURIREDACTION` to `true` or 1. | ||
|
|
||
| Otherwise, no action is required, and the default behavior will help enhance the privacy aspects of your application. | ||
|
|
||
| > [!NOTE] | ||
| > This switch also disables query string redaction in the default `IHttpClientFactory` logs. For more information, see [URI query redaction in IHttpClientFactory logs](query-redaction-logs.md). | ||
|
|
||
| ## Affected APIs | ||
|
|
||
| - [System.Net.Http.SocketsHttpHandler.Send](xref:System.Net.Http.HttpMessageHandler.Send(System.Net.Http.HttpRequestMessage,System.Threading.CancellationToken)) | ||
| - [System.Net.Http.SocketsHttpHandler.SendAsync](xref:System.Net.Http.HttpMessageHandler.SendAsync(System.Net.Http.HttpRequestMessage,System.Threading.CancellationToken)) |
67 changes: 67 additions & 0 deletions
67
docs/core/compatibility/networking/9.0/query-redaction-logs.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| --- | ||
| title: "URI query redaction in IHttpClientFactory logs" | ||
| description: Learn about the breaking change in networking in .NET 9 where the IHttpClientFactory implementation scrubs query strings in logs to enhance privacy. | ||
| ms.date: 11/5/2024 | ||
| ai-usage: ai-assisted | ||
| --- | ||
|
|
||
| # URI query redaction in IHttpClientFactory logs | ||
|
|
||
| In .NET 9, the default implementation of <xref:System.Net.Http.IHttpClientFactory> has been modified to scrub query strings when logging URI information. This change enhances privacy by preventing the logging of potentially sensitive information contained in query strings. For scenarios where logging query strings is necessary and deemed safe, you can override this behavior. | ||
|
|
||
| ## Version introduced | ||
|
|
||
| .NET 9 Preview 7 | ||
|
|
||
| ## Previous behavior | ||
|
|
||
| Previously, the default implementation of `IHttpClientFactory` logging included query strings in the messages passed to <xref:Microsoft.Extensions.Logging.ILogger>, which could inadvertently expose sensitive information. | ||
|
|
||
| ## New behavior | ||
|
|
||
| The messages passed to <xref:Microsoft.Extensions.Logging.ILogger> now have query strings replaced by a `*` character. | ||
|
|
||
| ## Type of breaking change | ||
|
|
||
| This change is a [behavioral change](../../categories.md#behavioral-change). | ||
|
|
||
| ## Reason for change | ||
|
|
||
| The primary reason for this change is to enhance privacy by reducing the risk of sensitive information being logged inadvertently. Query strings often contain sensitive data and excluding them from logs by default helps protect this information. | ||
|
|
||
| ## Recommended action | ||
|
|
||
| If your application relies on logging query strings and you're confident that it's safe to do so, you can enable query string logging globally by setting an AppContext switch in one of three ways: | ||
|
|
||
| - In the project file. | ||
|
|
||
| ```xml | ||
| <ItemGroup> | ||
| <RuntimeHostConfigurationOption Include="System.Net.Http.DisableUriRedaction" Value="true" /> | ||
| </ItemGroup> | ||
| ``` | ||
|
|
||
| - In the *runtimeconfig.json* file. | ||
|
|
||
| ```json | ||
| { | ||
| "runtimeOptions": { | ||
| "configProperties": { | ||
| "System.Net.Http.DisableUriRedaction": true | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| - Through an environment variable. | ||
|
|
||
| Set `DOTNET_SYSTEM_NET_HTTP_DISABLEURIREDACTION` to `true` or 1. | ||
|
|
||
| Otherwise, no action is required, and the default behavior will help enhance the privacy aspects of your application. | ||
|
|
||
| > [!NOTE] | ||
| > This switch also disables query string redaction in `HttpClient` EventSource events. For more information, see [URI query redaction in HttpClient EventSource events](query-redaction-events.md). | ||
|
|
||
| ## Affected APIs | ||
|
|
||
| - <xref:Microsoft.Extensions.DependencyInjection.HttpClientFactoryServiceCollectionExtensions.AddHttpClient*?displayProperty=fullName> |
44 changes: 44 additions & 0 deletions
44
docs/core/compatibility/networking/9.0/server-port-attribute.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| --- | ||
| title: "HttpClient metrics report `server.port` unconditionally" | ||
| description: Learn about the breaking change in networking in .NET 9 where HttpClient metrics now report the `server.port` attribute unconditionally to maintain compliance with Open Telemetry standards. | ||
| ms.date: 11/5/2024 | ||
| --- | ||
|
|
||
| # HttpClient metrics report `server.port` unconditionally | ||
|
|
||
| When [HttpClient metrics](../../../../fundamentals/networking/telemetry/metrics.md) was implemented in .NET 8, `server.port` was introduced as a [`Conditionally Required`](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/#conditionally-required) attribute in accordance with the state of the standard at that time. Being conditionally required meant that the port was only reported if it did not match the default port of the corresponding protocol (80 for HTTP, 443 for HTTPS). However, the standard [requirement level of the attribute](https://opentelemetry.io/docs/specs/semconv/http/http-spans/#http-client) has since been changed to `Required`. | ||
gewarren marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| To maintain compliance with the Open Telemetry standard while keeping the instrument's behaviors consistent with each other, the instruments `http.client.request.duration`, `http.client.connection.duration`, and `http.client.open_connections` have been changed to unconditionally report the `server.port` attribute. | ||
|
|
||
| This change can break existing queries in monitoring software like Prometheus. | ||
|
|
||
| ## Version introduced | ||
|
|
||
| .NET 9 Preview 7 | ||
|
|
||
| ## Previous behavior | ||
|
|
||
| `http.client.request.duration`, `http.client.connection.duration`, and `http.client.open_connections` reported the `server.port` attribute only if it did not match the corresponding protocol's default port (80 for HTTP, 443 for HTTPS). | ||
|
|
||
| ## New behavior | ||
|
|
||
| The `server.port` attribute is now unconditionally reported by the instruments `http.client.request.duration`, `http.client.connection.duration`, and `http.client.open_connections`. | ||
|
|
||
| ## Type of breaking change | ||
|
|
||
| This change is a [behavioral change](../../categories.md#behavioral-change). | ||
|
|
||
| ## Reason for change | ||
|
|
||
| The change maintains compliance with the [Open Telemetry specification](https://opentelemetry.io/docs/specs/semconv/http/http-spans/#http-client) while keeping `HttpClient` instruments consistent with each other. | ||
|
|
||
| ## Recommended action | ||
|
|
||
| No action is needed if you don't rely on [HttpClient metrics](../../../../fundamentals/networking/telemetry/metrics.md). If you use the `http.client.request.duration`, `http.client.connection.duration`, or `http.client.open_connections` instruments, this change might break existing queries in monitoring software like Prometheus. | ||
|
|
||
| ## Affected APIs | ||
|
|
||
| - `System.Net.Http.SocketsHttpHandler.Send(System.Net.Http.HttpRequestMessage,System.Threading.CancellationToken)` | ||
| - `System.Net.Http.SocketsHttpHandler.SendAsync(System.Net.Http.HttpRequestMessage,System.Threading.CancellationToken)` | ||
| - <xref:System.Net.Http.HttpClientHandler.Send(System.Net.Http.HttpRequestMessage,System.Threading.CancellationToken)?displayProperty=fullName> | ||
| - <xref:System.Net.Http.HttpClientHandler.SendAsync(System.Net.Http.HttpRequestMessage,System.Threading.CancellationToken)?displayProperty=fullName> | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.