如何在 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“先验知识”模式?的主要内容,如果未能解决你的问题,请参考以下文章