[release/7.0] Throw on incompatible WebSocket options #75014
Merged
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 #74473 to release/7.0
Fixes #74415
Fixes #74416
Customer Impact
We added support for WebSockets over HTTP/2 in .NET 7 RC1. As part of that change, we also introduced a new overload of
ConnectAsync
that accepts anHttpMessageInvoker
to allow reusing existing pooled connections.This PR fixes two issues related to user input validation:
The first is #74416 where existing options available on
ClientWebSocketOptions
(e.g.Proxy
,RemoteCertificateValidationCallback
) would be silently ignored if a customHttpMessageInvoker
was also specified.This PR makes it so that if any incompatible options are set and an invoker is specified, we will throw. This gives the developer a clear signal of what must be changed.
The second issue is #74415, where a developer attempting to utilize the new feature may fall into a performance trap. THE point of WebSockets over H/2 is the ability to multiplex WebSocket streams over a single transport connection. If the user only changes the
Version
orVersionPolicy
to allow for H/2, the implementation will use the requested protocol, but it will always open a new connection for each WebSocket, eliminating the benefit of said feature. To get the full benefit of H/2, the user must specify the invoker instance that should be reused by passing it toConnectAsync
.This PR makes it so that we throw if H/2 is requested but an invoker was not specified.
Testing
Added a number of targeted unit tests.
Risk
Low - these are new APIs introduced in recent 7.0 RC1 (technically in Preview 7, but the feature had a bug so it did not work), we believe very few users are consuming them already.
For those that are, we believe that scenarios that can be affected are misconfigurations.
With #74416 the options were being ignored, so any testing done by the user relying on these options would show that the scenario is broken. This change just makes debugging the issue easier for the developer.
With #74415 we are talking about a brand new feature that has limited support in the ecosystem (Kestrel is also adding it in 7.0). We believe the number of customers that are already using it with 7.0 RC1 in production is close to none, but we still consider it a breaking change against RC1 and will document it as such.
Any impacted user upgrading from RC1 to 7.0 RC2/RTW that did any testing prior to deployment to production would immediately observe the exception.