diff --git a/src/Common.CoreLib/Extensions/HttpExtensions.cs b/src/Common.CoreLib/Extensions/HttpExtensions.cs new file mode 100644 index 000000000..ea28ad20c --- /dev/null +++ b/src/Common.CoreLib/Extensions/HttpExtensions.cs @@ -0,0 +1,87 @@ +using System.Net; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; + +// ReSharper disable once CheckNamespace +namespace System +{ + public static class HttpExtensions + { + #region UseDefaultSendX 使用此扩展代替 Send,将 DefaultRequestVersion 与 DefaultVersionPolicy 赋值给 HttpRequestMessage + +#if NETSTANDARD + public static Version DefaultRequestVersion { get; set; } = HttpVersion.Version20; +#endif + + static void UseDefault(HttpClient httpClient, HttpRequestMessage request) + { +#if NETSTANDARD + request.Version = DefaultRequestVersion; +#else + request.Version = httpClient.DefaultRequestVersion; + request.VersionPolicy = httpClient.DefaultVersionPolicy; +#endif + } + + /// + public static Task UseDefaultSendAsync(this HttpClient httpClient, HttpRequestMessage request) + { + UseDefault(httpClient, request); + return httpClient.SendAsync(request); + } + + /// + public static Task UseDefaultSendAsync(this HttpClient httpClient, HttpRequestMessage request, HttpCompletionOption completionOption) + { + UseDefault(httpClient, request); + return httpClient.SendAsync(request, completionOption); + } + + /// + public static Task UseDefaultSendAsync(this HttpClient httpClient, HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken) + { + UseDefault(httpClient, request); + return httpClient.SendAsync(request, completionOption, cancellationToken); + } + + /// + public static Task UseDefaultSendAsync(this HttpClient httpClient, HttpRequestMessage request, CancellationToken cancellationToken) + { + UseDefault(httpClient, request); + return httpClient.SendAsync(request, cancellationToken); + } + +#if NET5_0_OR_GREATER + /// + public static HttpResponseMessage UseDefaultSend(this HttpClient httpClient, HttpRequestMessage request) + { + UseDefault(httpClient, request); + return httpClient.Send(request); + } + + /// + public static HttpResponseMessage UseDefaultSend(this HttpClient httpClient, HttpRequestMessage request, HttpCompletionOption completionOption) + { + UseDefault(httpClient, request); + return httpClient.Send(request, completionOption); + } + + /// + public static HttpResponseMessage UseDefaultSend(this HttpClient httpClient, HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken) + { + UseDefault(httpClient, request); + return httpClient.Send(request, completionOption, cancellationToken); + } + + /// + public static HttpResponseMessage UseDefaultSend(this HttpClient httpClient, HttpRequestMessage request, CancellationToken cancellationToken) + { + UseDefault(httpClient, request); + return httpClient.Send(request, cancellationToken); + } +#endif + + #endregion + } +} diff --git a/src/ST.Client/UI/ViewModels/Pages/DebugPageViewModel.cs b/src/ST.Client/UI/ViewModels/Pages/DebugPageViewModel.cs index 4d83f7bbb..ab05d71d1 100644 --- a/src/ST.Client/UI/ViewModels/Pages/DebugPageViewModel.cs +++ b/src/ST.Client/UI/ViewModels/Pages/DebugPageViewModel.cs @@ -15,6 +15,8 @@ using System.Globalization; using System.IO; using System.IO.Pipes; using System.Linq; +using System.Net; +using System.Net.Http; using System.Security; using System.Security.Cryptography.X509Certificates; using System.Text; @@ -74,6 +76,9 @@ namespace System.Application.UI.ViewModels public void DebugButton_Click() { + TestHttp3Quic(); + return; + //#if DEBUG // //TestAppUpdate(); // //return; @@ -94,6 +99,29 @@ namespace System.Application.UI.ViewModels }); } + public async void TestHttp3Quic() + { + // https://docs.microsoft.com/zh-cn/dotnet/core/extensions/httpclient-http3 + // https://devblogs.microsoft.com/dotnet/http-3-support-in-dotnet-6 + using HttpClient httpClient = new() + { +#if NET6_0_OR_GREATER + DefaultRequestVersion = HttpVersion.Version30, +#endif + }; + + using HttpRequestMessage request = new(HttpMethod.Get, "https://cloudflare-quic.com/"); + using var response = await httpClient.UseDefaultSendAsync(request); + + var htmlString = await response.Content.ReadAsStringAsync(); + + StringBuilder @string = new(); + @string.AppendFormatLine("request.Version: {0}", request.Version); + @string.AppendFormatLine("response.Version: {0}", response.Version); + @string.AppendLine(htmlString); + DebugString = @string.ToString(); + } + //static async void TestTextBoxWindow(int state) //{ // string? value = null; diff --git a/src/ST.Services.CloudService/Services/CloudService/ApiConnection.cs b/src/ST.Services.CloudService/Services/CloudService/ApiConnection.cs index 48f85f439..157c36ff6 100644 --- a/src/ST.Services.CloudService/Services/CloudService/ApiConnection.cs +++ b/src/ST.Services.CloudService/Services/CloudService/ApiConnection.cs @@ -506,7 +506,6 @@ namespace System.Application.Services.CloudService var request = new HttpRequestMessage(method, requestUri) { - Version = HttpVersion.Version20, Content = GetRequestContent( isSecurity, aes, @@ -555,7 +554,7 @@ namespace System.Application.Services.CloudService HandleHttpRequest(request); - var response = await client.SendAsync(request, + var response = await client.UseDefaultSendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken) .ConfigureAwait(false); @@ -757,10 +756,7 @@ namespace System.Application.Services.CloudService IApiResponse responseResult; try { - var request = new HttpRequestMessage(method, requestUri) - { - Version = HttpVersion.Version20, - }; + var request = new HttpRequestMessage(method, requestUri); JWTEntity? jwt = null; @@ -773,7 +769,7 @@ namespace System.Application.Services.CloudService HandleHttpRequest(request); - var response = await client.SendAsync(request, + var response = await client.UseDefaultSendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken) .ConfigureAwait(false); diff --git a/src/Startup2.cs b/src/Startup2.cs index a187e7299..c521c7e21 100644 --- a/src/Startup2.cs +++ b/src/Startup2.cs @@ -275,7 +275,7 @@ namespace System.Application c.DefaultRequestVersion = HttpVersion.Version20; #endif #if NET5_0_OR_GREATER - c.DefaultVersionPolicy = HttpVersionPolicy.RequestVersionExact; + c.DefaultVersionPolicy = HttpVersionPolicy.RequestVersionOrHigher; #endif }, configureHandler: #if NETCOREAPP2_1_OR_GREATER diff --git a/tests/ST.Client.UnitTest/SetupFixture.shared.cs b/tests/ST.Client.UnitTest/SetupFixture.shared.cs index 1a8024dbf..f1b4722dd 100644 --- a/tests/ST.Client.UnitTest/SetupFixture.shared.cs +++ b/tests/ST.Client.UnitTest/SetupFixture.shared.cs @@ -55,7 +55,7 @@ namespace System.Application public static void OneTimeTearDownCore() { #if !Desktop_UnitTest && !__ANDROID__ - HostsFileTest.DeleteAllTempFileName(); + HostsFileTest.DeleteAllTempFileName(); #endif } @@ -102,7 +102,7 @@ namespace System.Application c.DefaultRequestVersion = HttpVersion.Version20; #endif #if NET5_0_OR_GREATER - c.DefaultVersionPolicy = HttpVersionPolicy.RequestVersionExact; + c.DefaultVersionPolicy = HttpVersionPolicy.RequestVersionOrHigher; #endif }, configureHandler: #if NETCOREAPP2_1_OR_GREATER