rksoftware

Visual Studio とか C# とかが好きです

.NET Core 3 で HTTP/2 を使う

.NET Core 3.0 の時の新機能として HTTP/2 のサポートがありました。

リンク先に書かれていますが、ただ HttpClient を使うだけではなく少し設定? がいるとのことです。
設定と言ってもプロパティに使いたいバージョン(2.0)を指定するだけですが。

少しだけ説明が長いので、分かる人には一目で分かる(かもしれない)記事を書きました。

今回は実際に動かして試してみます。

■ 確認方法

.NET Core の Web サーバは HTTP/2 に対応しています。なので、ASP.NET Core に対してコンソールアプリ(.NET Core) から HTTPS 通信して採用されるプロトコルを確認します。
サーバサイドで Request.Protocol で確認できます。"HTTP/1.1" または "HTTP/2.0" という文字列が入っています。

■ 確認プロジェクト

ASP.NET Core WebAPI プロジェクトとコンソールアプリプロジェクトの 2 プロジェクトを作ります。

ASP.NET Core WebAPI プロジェクト

テンプレートから作成した状態で少しコードがあるのでそこにプロトコル確認用のコードを追加します。
今回は Get メソッドに引数 message を足し、Console.WriteLine で足した引数 message とプロトコル Request.Protocol を出力するようにしました。

[HttpGet]
public IEnumerable<WeatherForecast> Get(/* 引数を追加 */ string message)
{
    // バージョンの出力を追加
    Console.WriteLine($"{message}:{Request.Protocol}");

    var rng = new Random();
    return Enumerable.Range(1, 5).Select(index => new WeatherForecast
    {
        Date = DateTime.Now.AddDays(index),
        TemperatureC = rng.Next(-20, 55),
        Summary = Summaries[rng.Next(Summaries.Length)]
    })
    .ToArray();
}

コンソールアプリプロジェクト

WebAPI の Get メソッドを 4 回呼びます。
Version 2.0 を指定する場合は、message パラメータに 2.0 とバージョンを入れています。Version を指定しない場合は 1.1 です。

static async Task Main(string[] args)
{
    var baseAddress = new Uri("https://localhost:44316/");

    {// Request に Version を付けるパターン
        var client = new HttpClient() { BaseAddress = baseAddress };

        // HTTP/1.1 request
        using (var response = await client.GetAsync("/weatherforecast?message=request1.1"))
            Console.WriteLine(response.Content);

        // HTTP/2 request
        using (var request = new HttpRequestMessage(HttpMethod.Get, "/weatherforecast?message=request2.0") { Version = new Version(2, 0) })
        using (var response = await client.SendAsync(request))
            Console.WriteLine(response.Content);
    }

    {// HttpClient に Version を付けるパターン
        {
            var client = new HttpClient()
            {
                BaseAddress = baseAddress
            };

            // HTTP/1.1 is default
            using (var response = await client.GetAsync("/weatherforecast?message=HttpClient1.1"))
                Console.WriteLine(response.Content);
        }
        {
            var client = new HttpClient()
            {
                BaseAddress = baseAddress,
                DefaultRequestVersion = new Version(2, 0)
            };

            // HTTP/2 is default
            using (var response = await client.GetAsync("/weatherforecast?message=HttpClient2.0"))
                Console.WriteLine(response.Content);
        }
    }
}

■ 実行

実行してみると次の文字列が出力されます。

request1.1:HTTP/1.1
request2.0:HTTP/2.0
HttpClient1.1:HTTP/1.1
HttpClient2.0:HTTP/2.0

確かにバージョンを指定することで HTTP/2 が使えていることが確認できました。

今回書いた確認コードは GitHub に置いてあります。