Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/dotnet/runtime.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKatya Sokolova <esokolov@microsoft.com>2022-08-13 00:04:34 +0300
committerGitHub <noreply@github.com>2022-08-13 00:04:34 +0300
commit3824cb2931453d7818c6fff0762cc6f1c536a147 (patch)
tree52ab3ee2cf2cf218c3e20ca45183babcd84667dd
parent280c373c7b840bcf2226aac343e8a4e27144ff1d (diff)
Handle web socket downgrade when HTTP/2 not enabled (#73843)
* Handle downgrade when HTTP/2 not enabled * Update src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs Co-authored-by: Natalia Kondratyeva <knatalia@microsoft.com> * feedback * Force 1.1 for non-secure web request if policy allows Co-authored-by: Natalia Kondratyeva <knatalia@microsoft.com>
-rw-r--r--src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectHelper.cs9
-rw-r--r--src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs15
-rw-r--r--src/libraries/System.Net.WebSockets.Client/src/System/Net/WebSockets/WebSocketHandle.Managed.cs5
-rw-r--r--src/libraries/System.Net.WebSockets.Client/tests/ClientWebSocketTestBase.cs5
-rw-r--r--src/libraries/System.Net.WebSockets.Client/tests/ConnectTest.Http2.cs53
5 files changed, 77 insertions, 10 deletions
diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectHelper.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectHelper.cs
index 04c5bef5d95..d2a6f430a9b 100644
--- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectHelper.cs
+++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectHelper.cs
@@ -88,7 +88,14 @@ namespace System.Net.Http
throw CancellationHelper.CreateOperationCanceledException(e, cancellationToken);
}
- throw new HttpRequestException(SR.net_http_ssl_connection_failed, e);
+ HttpRequestException ex = new HttpRequestException(SR.net_http_ssl_connection_failed, e);
+ if (request.IsExtendedConnectRequest)
+ {
+ // Extended connect request is negotiating strictly for ALPN = "h2" because HttpClient is unaware of a possible downgrade.
+ // At this point, SSL connection for HTTP / 2 failed, and the exception should indicate the reason for the external client / user.
+ ex.Data["HTTP2_ENABLED"] = false;
+ }
+ throw ex;
}
// Handle race condition if cancellation happens after SSL auth completes but before the registration is disposed
diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs
index 354b50b5966..e4afdd294fc 100644
--- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs
+++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs
@@ -426,7 +426,13 @@ namespace System.Net.Http
{
Debug.Assert(desiredVersion == 2 || desiredVersion == 3);
- throw new HttpRequestException(SR.Format(SR.net_http_requested_version_cannot_establish, request.Version, request.VersionPolicy, desiredVersion), inner);
+ HttpRequestException ex = new HttpRequestException(SR.Format(SR.net_http_requested_version_cannot_establish, request.Version, request.VersionPolicy, desiredVersion), inner);
+ if (request.IsExtendedConnectRequest && desiredVersion == 2)
+ {
+ ex.Data["HTTP2_ENABLED"] = false;
+ }
+
+ throw ex;
}
private bool CheckExpirationOnGet(HttpConnectionBase connection)
@@ -1122,12 +1128,7 @@ namespace System.Net.Http
// Throw if fallback is not allowed by the version policy.
if (request.VersionPolicy != HttpVersionPolicy.RequestVersionOrLower)
{
- HttpRequestException exception = new HttpRequestException(SR.Format(SR.net_http_requested_version_server_refused, request.Version, request.VersionPolicy), e);
- if (request.IsExtendedConnectRequest)
- {
- exception.Data["HTTP2_ENABLED"] = false;
- }
- throw exception;
+ throw new HttpRequestException(SR.Format(SR.net_http_requested_version_server_refused, request.Version, request.VersionPolicy), e);
}
if (NetEventSource.Log.IsEnabled())
diff --git a/src/libraries/System.Net.WebSockets.Client/src/System/Net/WebSockets/WebSocketHandle.Managed.cs b/src/libraries/System.Net.WebSockets.Client/src/System/Net/WebSockets/WebSocketHandle.Managed.cs
index 29ddf98cafe..6bb365012ef 100644
--- a/src/libraries/System.Net.WebSockets.Client/src/System/Net/WebSockets/WebSocketHandle.Managed.cs
+++ b/src/libraries/System.Net.WebSockets.Client/src/System/Net/WebSockets/WebSocketHandle.Managed.cs
@@ -53,7 +53,8 @@ namespace System.Net.WebSockets
bool disposeResponse = false;
- bool tryDowngrade = false;
+ // force non-secure request to 1.1 whenever it is possible as HttpClient does
+ bool tryDowngrade = uri.Scheme == UriScheme.Ws && (options.HttpVersion == HttpVersion.Version11 || options.HttpVersionPolicy == HttpVersionPolicy.RequestVersionOrLower);
try
{
@@ -63,7 +64,7 @@ namespace System.Net.WebSockets
{
HttpRequestMessage request;
if (!tryDowngrade && options.HttpVersion >= HttpVersion.Version20
- || (options.HttpVersion == HttpVersion.Version11 && options.HttpVersionPolicy == HttpVersionPolicy.RequestVersionOrHigher))
+ || (options.HttpVersion == HttpVersion.Version11 && options.HttpVersionPolicy == HttpVersionPolicy.RequestVersionOrHigher && uri.Scheme == UriScheme.Wss))
{
if (options.HttpVersion > HttpVersion.Version20 && options.HttpVersionPolicy != HttpVersionPolicy.RequestVersionOrLower)
{
diff --git a/src/libraries/System.Net.WebSockets.Client/tests/ClientWebSocketTestBase.cs b/src/libraries/System.Net.WebSockets.Client/tests/ClientWebSocketTestBase.cs
index 203040e4ffc..a32587bc862 100644
--- a/src/libraries/System.Net.WebSockets.Client/tests/ClientWebSocketTestBase.cs
+++ b/src/libraries/System.Net.WebSockets.Client/tests/ClientWebSocketTestBase.cs
@@ -26,6 +26,11 @@ namespace System.Net.WebSockets.Client.Tests
new object[] { o[0], false },
new object[] { o[0], true }
}).ToArray();
+ public static readonly object[][] SecureEchoServersAndBoolean = new object[][]
+ {
+ new object[] { Test.Common.Configuration.WebSockets.SecureRemoteEchoServer, false },
+ new object[] { Test.Common.Configuration.WebSockets.SecureRemoteEchoServer, true }
+ };
public const int TimeOutMilliseconds = 30000;
public const int CloseDescriptionMaxLength = 123;
diff --git a/src/libraries/System.Net.WebSockets.Client/tests/ConnectTest.Http2.cs b/src/libraries/System.Net.WebSockets.Client/tests/ConnectTest.Http2.cs
index aa14fd93ab2..1ec2f1ee39f 100644
--- a/src/libraries/System.Net.WebSockets.Client/tests/ConnectTest.Http2.cs
+++ b/src/libraries/System.Net.WebSockets.Client/tests/ConnectTest.Http2.cs
@@ -96,6 +96,59 @@ namespace System.Net.WebSockets.Client.Tests
);
}
+ [OuterLoop("Uses external servers", typeof(PlatformDetection), nameof(PlatformDetection.LocalEchoServerIsNotAvailable))]
+ [Theory]
+ [MemberData(nameof(SecureEchoServersAndBoolean))]
+ [SkipOnPlatform(TestPlatforms.Browser, "System.Net.Sockets is not supported on this platform")]
+ public async Task ConnectAsync_Http11Server_DowngradeFail(Uri server, bool useHandler)
+ {
+ using (var cws = new ClientWebSocket())
+ using (var cts = new CancellationTokenSource(TimeOutMilliseconds))
+ {
+ cws.Options.HttpVersion = HttpVersion.Version20;
+ cws.Options.HttpVersionPolicy = Http.HttpVersionPolicy.RequestVersionExact;
+ Task t;
+ if (useHandler)
+ {
+ var handler = new SocketsHttpHandler();
+ t = cws.ConnectAsync(server, new HttpMessageInvoker(handler), cts.Token);
+ }
+ else
+ {
+ t = cws.ConnectAsync(server, cts.Token);
+ }
+ var ex = await Assert.ThrowsAnyAsync<WebSocketException>(() => t);
+ Assert.IsType<HttpRequestException>(ex.InnerException);
+ Assert.True(ex.InnerException.Data.Contains("HTTP2_ENABLED"));
+ Assert.Equal(WebSocketState.Closed, cws.State);
+ }
+ }
+
+ [OuterLoop("Uses external servers", typeof(PlatformDetection), nameof(PlatformDetection.LocalEchoServerIsNotAvailable))]
+ [Theory]
+ [MemberData(nameof(EchoServersAndBoolean))]
+ [SkipOnPlatform(TestPlatforms.Browser, "System.Net.Sockets is not supported on this platform")]
+ public async Task ConnectAsync_Http11Server_DowngradeSuccess(Uri server, bool useHandler)
+ {
+ using (var cws = new ClientWebSocket())
+ using (var cts = new CancellationTokenSource(TimeOutMilliseconds))
+ {
+ cws.Options.HttpVersion = HttpVersion.Version20;
+ cws.Options.HttpVersionPolicy = Http.HttpVersionPolicy.RequestVersionOrLower;
+ if (useHandler)
+ {
+ var handler = new SocketsHttpHandler();
+ await cws.ConnectAsync(server, new HttpMessageInvoker(handler), cts.Token);
+ }
+ else
+ {
+ await cws.ConnectAsync(server, cts.Token);
+ }
+ Assert.Equal(WebSocketState.Open, cws.State);
+ }
+ }
+
+
[Theory]
[InlineData(false)]
[InlineData(true)]