Inti Gonzalez-Herrera
Inti Gonzalez-Herrera

Reputation: 308

How to specify HTTP/2 "prior knowledge" mode for HttpClient in dotnet core?

Using dotnet Core 3.1, the following server accepts HTTP/2 requests:

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;
        }
    }
}

For instance, you get a response if you try: curl --silent --http2-prior-knowledge http://localhost:8080

My question is about how to actually do what curl is doing ? But in C#.

I have tried:

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);
           }
      }
}

But I just get an exception.

Is it possible to use prior knowledge mode with HttpClient in C# and dotnet Core ?

Upvotes: 3

Views: 3023

Answers (2)

cwschroeder
cwschroeder

Reputation: 66

I am on net5.0 and could only make it work when setting the VersionPolicy explicitly

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

Upvotes: 3

Fei Han
Fei Han

Reputation: 27793

My question is about how to actually do what curl is doing ? But in C#.

Please try to set the System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport switch to true, like below.

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);
    }
}

Test Result

enter image description here

Upvotes: 2

Related Questions