[release/6.0] Allow retaining the original casing for known header values #80754
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.
Backport of #64702 to release/6.0, gated behind an AppContext switch.
Customer Impact
Starting with .NET Core 2.1 and later expanded in .NET 5.0, we introduced a performance optimization where we avoid allocating strings for common well-known header values.
We did this in a case-insensitive manner, so if the server sent us
Connection: close
orConnection: CLOSE
, they would both be exposed to the user asclose
.As services are migrating from Framework to Core, this represents a change in behavior that can't be avoided as the optimization is taking place lower in the stack before the information is exposed to the user.
Clients running different versions of .NET may therefore not agree on the exact response provided by the server, which can break scenarios such as signature validation.
We stopped doing case-insensitive matching in .NET 7.0, and this PR brings the option to do the same on the 6.0 LTS release to unblock migration.
Testing
I added a targeted test to verify the expected behavior is observed if the
AppContext
switch is set.The customer validated the new behavior using a private build of
System.Net.Http
.Risk
Practically zero. The change in behavior is hidden behind an
AppContext
switch.