diff --git a/docs/core/compatibility/9.0.md b/docs/core/compatibility/9.0.md index 5ace50ef8f2ee..ebf7cd2618718 100644 --- a/docs/core/compatibility/9.0.md +++ b/docs/core/compatibility/9.0.md @@ -80,9 +80,13 @@ If you're migrating an app to .NET 9, the breaking changes listed here might aff | Title | Type of change | Introduced version | |-----------------------------------------------------------------------------------|---------------------|--------------------| +| [API obsoletions](core-libraries/9.0/obsolete-apis-with-custom-diagnostics.md) | Source incompatible | Preview 6 | +| [HttpClient metrics report `server.port` unconditionally](networking/9.0/server-port-attribute.md) | Behavioral change | Preview 7 | | [HttpClientFactory logging redacts header values by default](networking/9.0/redact-headers.md) | Behavioral change | RC 1 | +| [HttpClientFactory uses SocketsHttpHandler as primary handler](networking/9.0/default-handler.md) | Behavioral change | Preview 6 | | [HttpListenerRequest.UserAgent is nullable](networking/9.0/useragent-nullable.md) | Source incompatible | Preview 1 | -| [API obsoletions](core-libraries/9.0/obsolete-apis-with-custom-diagnostics.md) | Source incompatible | Preview 6 | +| [URI query redaction in HttpClient EventSource events](networking/9.0/query-redaction-events.md) | Behavioral change | Preview 7 | +| [URI query redaction in IHttpClientFactory logs](networking/9.0/query-redaction-logs.md) | Behavioral change | Preview 7 | ## SDK and MSBuild diff --git a/docs/core/compatibility/core-libraries/6.0/obsolete-apis-with-custom-diagnostics.md b/docs/core/compatibility/core-libraries/6.0/obsolete-apis-with-custom-diagnostics.md index dd1ea8c221bb3..387c1a281d735 100644 --- a/docs/core/compatibility/core-libraries/6.0/obsolete-apis-with-custom-diagnostics.md +++ b/docs/core/compatibility/core-libraries/6.0/obsolete-apis-with-custom-diagnostics.md @@ -16,7 +16,7 @@ The following table lists the custom diagnostic IDs and their corresponding warn | Diagnostic ID | Description | Severity | | - | - | -| [SYSLIB0013](../../../../fundamentals/syslib-diagnostics/syslib0013.md) | can corrupt the Uri string in some cases. Consider using for query string components instead. | Warning | +| [SYSLIB0013](../../../../fundamentals/syslib-diagnostics/syslib0013.md) | can corrupt the URI string in some cases. Consider using for query string components instead. | Warning | | [SYSLIB0014](../../../../fundamentals/syslib-diagnostics/syslib0014.md) | , , , and are obsolete. Use instead. | Warning | | [SYSLIB0015](../../../../fundamentals/syslib-diagnostics/syslib0015.md) | has no effect in .NET 6+. | Warning | | [SYSLIB0016](../../../../fundamentals/syslib-diagnostics/syslib0016.md) | Use the overloads that accept arguments for better performance and fewer allocations. | Warning | diff --git a/docs/core/compatibility/networking/9.0/default-handler.md b/docs/core/compatibility/networking/9.0/default-handler.md new file mode 100644 index 0000000000000..c9d9ad9529aef --- /dev/null +++ b/docs/core/compatibility/networking/9.0/default-handler.md @@ -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 pipeline for named and typed 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 . 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 , , and . + +With this change, the default primary handler is a on platforms that support it. On other platforms, for example, .NET Framework, continues to be used. + +`SocketsHttpHandler` now also has the property preset to match the 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 . + +For example, the same code from the [Previous behavior](#previous-behavior) section now throws an : + +> 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 . Because `HttpClientFactory` can't rotate such handlers, they might end up not respecting DNS changes. + +This problem can be mitigated by using , which has an option to control . Similarly to , 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 (for example, via ). + +## 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 : + + ```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 + +- +- diff --git a/docs/core/compatibility/networking/9.0/query-redaction-events.md b/docs/core/compatibility/networking/9.0/query-redaction-events.md new file mode 100644 index 0000000000000..416e58dec1b00 --- /dev/null +++ b/docs/core/compatibility/networking/9.0/query-redaction-events.md @@ -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 events emitted by and (`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 + + + + ``` + +- 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)) diff --git a/docs/core/compatibility/networking/9.0/query-redaction-logs.md b/docs/core/compatibility/networking/9.0/query-redaction-logs.md new file mode 100644 index 0000000000000..2113fc1ee17b0 --- /dev/null +++ b/docs/core/compatibility/networking/9.0/query-redaction-logs.md @@ -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 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 , which could inadvertently expose sensitive information. + +## New behavior + +The messages passed to 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 + + + + ``` + +- 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 + +- diff --git a/docs/core/compatibility/networking/9.0/server-port-attribute.md b/docs/core/compatibility/networking/9.0/server-port-attribute.md new file mode 100644 index 0000000000000..156c014d82167 --- /dev/null +++ b/docs/core/compatibility/networking/9.0/server-port-attribute.md @@ -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) were added 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`. + +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)` +- +- diff --git a/docs/core/compatibility/toc.yml b/docs/core/compatibility/toc.yml index ba0c777f4a65a..55894f0b99751 100644 --- a/docs/core/compatibility/toc.yml +++ b/docs/core/compatibility/toc.yml @@ -74,10 +74,18 @@ items: href: jit/9.0/sve-apis.md - name: Networking items: + - name: HttpClient metrics report `server.port` unconditionally + href: networking/9.0/server-port-attribute.md - name: HttpClientFactory logging redacts header values by default href: networking/9.0/redact-headers.md + - name: HttpClientFactory uses SocketsHttpHandler as primary handler + href: networking/9.0/default-handler.md - name: HttpListenerRequest.UserAgent is nullable href: networking/9.0/useragent-nullable.md + - name: Uri query redaction in HttpClient EventSource events + href: networking/9.0/query-redaction-events.md + - name: Uri query redaction in IHttpClientFactory logs + href: networking/9.0/query-redaction-logs.md - name: SDK and MSBuild items: - name: "'dotnet workload' commands output change" @@ -515,7 +523,7 @@ items: - name: WPF items: - name: Revert behavior with text drag-and-drop operations - href: wpf/7.0/drag-and-drop.md + href: wpf/7.0/drag-and-drop.md - name: .NET 6 items: - name: Overview @@ -1694,10 +1702,18 @@ items: items: - name: .NET 9 items: + - name: HttpClient metrics report `server.port` unconditionally + href: networking/9.0/server-port-attribute.md - name: HttpClientFactory logging redacts header values by default href: networking/9.0/redact-headers.md + - name: HttpClientFactory uses SocketsHttpHandler as primary handler + href: networking/9.0/default-handler.md - name: HttpListenerRequest.UserAgent is nullable href: networking/9.0/useragent-nullable.md + - name: Uri query redaction in HttpClient EventSource events + href: networking/9.0/query-redaction-events.md + - name: Uri query redaction in IHttpClientFactory logs + href: networking/9.0/query-redaction-logs.md - name: .NET 8 items: - name: SendFile throws NotSupportedException for connectionless sockets