HTTP Protocol in ASP.NET Core

In this blog post, which will be a quick read, I’m going to begin what I expect to be a long-running endeavour, to dig into new APIs available in .NET 5 and ASP.NET Core 5.0. This time, I’m going to look at a new helper for HTTP protocol versions.

WHAT ARE HTTP PROTOCOL VERSIONS?

Through the years, the HTTP protocol standard has evolved. To distinguish those changes, versions have been used so that clients and servers can establish the version in use. The version is included as part of the HTTP request and response. Today, the most common protocols are HTTP/1.1 and HTTP/2 with a standard around HTTP/3 already being defined.

INTRODUCING THE HTTPPROTOCOL HELPER CLASS

James Newton-King introduced an issue in the ASP.NET Core repository on GitHub suggesting the addition of a helper class for HTTP protocols, similar to the existing HttpMethods helper. The objective was to remove the need to use magic strings when determining the protocol from, for example, the HttpRequest. James then submitted a pull request to add the feature which is available in ASP.NET Core 5.0 preview 1.

This feature is likely to be of limited use for most people as it’s a reasonably rare requirement outside of framework developers. Still, I’ll cover it here for your curiosity!

USING HTTPPROTOCOL

When developing an ASP.NET Core 5.0 enabled project with the Web SDK, the package you require will be available in your application.

You’ll need to add a using directive to your file as follows.

using Microsoft.AspNetCore.Http;

The first thing that the class provides is a set of static (we’ll come back to that below) strings representing the current protocol versions. We can access and use these strings when we need to provide a protocol.

var protocol10 = HttpProtocol.Http10; // "HTTP/1.0"
var protocol11 = HttpProtocol.Http11; // "HTTP/1.1"
var protocol20 = HttpProtocol.Http2; // "HTTP/2"
var protocol30 = HttpProtocol.Http3; // "HTTP/3"

You may wonder, why are the strings defined as static and not const? The comments in the HttpProtocol source code explain the reason which I found enlightening.

// We are intentionally using 'static readonly' here instead of 'const'.
// 'const' values would be embedded into each assembly that used them
// and each consuming assembly would have a different 'string' instance.
// Using .'static readonly' means that all consumers get these exact same
// 'string' instance, which means the 'ReferenceEquals' checks below work
// and allow us to optimize comparisons when these constants are used.

On this point, the class provides a few simple methods to perform protocol checking. For example, we could do the following, which will return false since the passed in the protocol is not HTTP/2.

public static bool IsHttp2(string protocol)
{
    return object.ReferenceEquals(Http2, protocol) || StringComparer.OrdinalIgnoreCase.Equals(Http2, protocol);
}

We can also pass a string literal to compare such as this comparison which returns true.

var isHttp11Protocol = HttpProtocol.IsHttp11("http/1.1"); // true

You’ll note that the protocol check here is not case sensitive.

Exploring the code, we can see an example of the IsHttp2 method.

public static bool IsHttp2(string protocol)
{
    return object.ReferenceEquals(Http2, protocol) || StringComparer.OrdinalIgnoreCase.Equals(Http2, protocol);
}

The optimisation here makes use of the conditional logical OR operator || which computes the logical OR of its operands, but doesn’t evaluate the right-hand operand if the left-hand operand evaluates to true.

In the preceding example, when a reference to one of the static protocol strings is passed in, the ReferenceEquals immediately returns true. Otherwise, the check falls back to comparing the strings directly using OrdinalIgnoreCase.

The final method on the HttpProtocol helper class allows retrieval of a protocol using just a Version.

var finalProtocol = HttpProtocol.GetHttpProtocol(new Version(major: 2, minor: 0)); // "HTTP/2";

In this case, we construct a new instance of Version representing 2.0 and pass that into GetHttpProtocol. This returns a reference to the Http2 string. Passing a version that has a value which does not match a known HTTP protocol version causes an ArgumentOutOfRangeException to be thrown.

Anjali Punjab

Anjali Punjab is a freelance writer, blogger, and ghostwriter who develops high-quality content for businesses. She is also a HubSpot Inbound Marketing Certified and Google Analytics Qualified Professional.