如何在 dotnet core 中为 HttpClient 指定 HTTP/2“先验知识”模式?

Posted

技术标签:

【中文标题】如何在 dotnet core 中为 HttpClient 指定 HTTP/2“先验知识”模式?【英文标题】:How to specify HTTP/2 "prior knowledge" mode for HttpClient in dotnet core? 【发布时间】:2020-06-18 13:54:42 【问题描述】:

使用 dotnet Core 3.1,以下服务器接受 HTTP/2 请求:

using System;
using System.Threading.Tasks;
using System.Net.Http;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore;
using System.Threading;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Server.Kestrel.Core;

namespace http2

    class Program
    
        static void Main(string[] args)
        
            CreateWebHostBuilder(args).Build().Run();
        

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>()
                .ConfigureKestrel((context, serverOptions) =>
                
                    serverOptions.ListenLocalhost(8080, listenOptions =>
                    
                        listenOptions.Protocols = HttpProtocols.Http2; // this line is important
                    );
                );
    

    class Startup
    
        public void Configure(IApplicationBuilder app)
        
            app.Run(context => ProcessAsync(context));
        

        internal async Task<bool> ProcessAsync(HttpContext context)
        
            await context.Response.WriteAsync("This is the response: toto");
            return true;
        
    

例如,如果您尝试: curl --silent --http2-prior-knowledge http://localhost:8080

我的问题是关于如何实际执行 curl 正在执行的操作?但是在 C# 中。

我试过了:

static void ClientCode(object parameter)

      SocketsHttpHandler handler = new SocketsHttpHandler();
      using (var client = new HttpClient(handler))
      
           var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost:8080");
           request.Version = new Version(2, 0);

           var response = client.SendAsync(request).Result;
           if (response.IsSuccessStatusCode)
           
                var s = response.Content.ReadAsStringAsync().Result;
                Console.WriteLine(s);
           
      

但我只是得到了一个例外。

是否可以在 C# 和 dotnet Core 中将 prior knowledge mode 与 HttpClient 一起使用?

【问题讨论】:

【参考方案1】:

我的问题是关于如何实际做 curl 正在做的事情?但是在 C# 中。

请尝试将System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport 开关设置为true,如下所示。

AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);

SocketsHttpHandler handler = new SocketsHttpHandler();
using (var client = new HttpClient(handler))

    var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost:8080");
    request.Version = new Version(2, 0);

    var response = client.SendAsync(request).Result;

    if (response.IsSuccessStatusCode)
    
        var s = response.Content.ReadAsStringAsync().Result;
        Console.WriteLine(s);
    

测试结果

【讨论】:

是的,成功了。这有点 hacky,因为它正在使用该字符串,但它确实有效。【参考方案2】:

我在 net5.0 上,只有在明确设置 VersionPolicy 时才能使其工作

var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost:5001/test");
request.Version = new Version(2, 0);
request.VersionPolicy = HttpVersionPolicy.RequestVersionExact;

【讨论】:

以上是关于如何在 dotnet core 中为 HttpClient 指定 HTTP/2“先验知识”模式?的主要内容,如果未能解决你的问题,请参考以下文章

如何正确停止运行 dotnet core web 应用程序?

如何通过 FTP 发布 dotnet core web 后端?

如何在 dotnet core web api 中设置起始页?

如何在 dotnet core 中验证非对称签名的 JWT?

如何强制降级 dotnet core 中的传递依赖

如何在 Entity Framework Core cli 工具中使用来自 dotnet 6 最小 API 的配置