ASP.NET Core 2.2.0-preview1: HTTP/2 in Kestrel

As part of the 2.2.0-preview1 release, we’ve added support for HTTP/2 in Kestrel.

What is HTTP/2?

HTTP/2 is a major revision of the HTTP protocol. Some of the notable features of HTTP/2 are support for header compression and fully multiplexed streams over the same connection. While HTTP/2 preserves HTTP’s semantics (HTTP headers, methods, etc) it is a breaking change from HTTP/1.x on how this data is framed and sent over the wire.

As a consequence of this change in framing, servers and clients need to negotiate the protocol version used. While it is possible to have prior knowledge between the server and the client on the protocol, all major browsers support ALPN as the only way to establish a HTTP/2 connection.

Application-Layer Protocol Negotiation (ALPN)

Application-Layer Protocol Negotiation (ALPN) is a TLS extension that allows the server and client negotiate the protocol version used as part of their TLS handshake.

How do I use it?

In 2.2.0-preview1 of Kestrel, HTTP/2 is enabled by default (we may change this in subsequent releases). Since most browsers already support HTTP/2 any request you make will already happen over HTTP/2 provided certain conditions are met:

  • The request is made over an HTTPS connection.
  • The native crypto library used by .NET Core on your platform supports ALPN

In the event that either of these conditions is unmet, the server and client will transparently fallback to using HTTP1.1.

The default binding in Kestrel advertises support for both HTTP/1.x and HTTP/2 via ALPN. You can always configure additional bindings via KestrelServerOptions. For example,

WebHost.CreateDefaultBuilder()
    .ConfigureKestrel(options =>
    {
        options.Listen(IPAddress.Any, 8080, listenOptions =>
        {
            listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
            listenOptions.UseHttps("testcert.pfx", "testPassword")
        }); 
    })
    .UseStartup<Startup>();

If you do not enable HTTPS/TLS then Kestrel will be unable to use ALPN to negotiate HTTP/2 connections.

It is possible to establish a HTTP/2 connection in Kestrel using prior knowledge on all platforms (since we don’t rely on ALPN). However, no major browser supports prior knowledge HTTP/2 connections. This approach does not allow for graceful fallback to HTTP/1.x.

WebHost.CreateDefaultBuilder()
    .ConfigureKestrel(options =>
    {
        options.Listen(IPAddress.Any, 8080, listenOptions =>
        {
            listenOptions.Protocols = HttpProtocols.Http2;
        }); 
    })
    .UseStartup<Startup>();

Caveats

As mentioned earlier, it is only possible to negotiate an HTTP/2 connection if the native crypto library on your server supports ALPN.

ALPN is supported on:

  • .NET Core on Windows 8.1/Windows Server 2012 R2 or higher
  • .NET Core on Linux with OpenSSL 1.0.2 or higher (e.g., Ubuntu 16.04)

ALPN is not supported on:

  • .NET Framework 4.x on Windows
  • .NET Core on Linux with OpenSSL older than 1.0.2
  • .NET Core on OS X

What’s missing in Kestrel’s HTTP/2?

  • Server Push: An HTTP/2-compliant server is allowed to send resources to a client before they have been requested by the client. This is a feature we’re currently evaluating, but haven’t planned to add support for yet.
  • Stream Prioritization: The HTTP/2 standard allows for clients to send a hint to the server to express preference for the priority of processing streams. Kestrel currently does not act upon hints sent by the client.
  • HTTP Trailers: Trailers are HTTP headers that can be sent after the message body in both HTTP requests and responses.

What’s coming next?

In ASP.NET Core 2.2,

  • Hardening work on HTTP/2 in Kestrel. As HTTP/2 allows multiplexed streams over the same TCP connection, we need to introduce HTTP/2 specific limits as part of the hardening.
  • Performance work on HTTP/2.

Feedback

The best place to provide feedback is by opening issues at https://github.com/aspnet/KestrelHttpServer/issues.