Browse Source

Add HttpProtocol (#18049)

James Newton-King 6 years ago
parent
commit
df712cc4a9

+ 1 - 1
src/Hosting/TestHost/src/ClientHandler.cs

@@ -100,7 +100,7 @@ namespace Microsoft.AspNetCore.TestHost
                 if (request.Version == HttpVersion.Version20)
                 {
                     // https://tools.ietf.org/html/rfc7540
-                    req.Protocol = "HTTP/2";
+                    req.Protocol =  HttpProtocol.Http2;
                 }
                 else
                 {

+ 2 - 2
src/Hosting/TestHost/src/HttpContextBuilder.cs

@@ -41,7 +41,7 @@ namespace Microsoft.AspNetCore.TestHost
             _requestLifetimeFeature = new RequestLifetimeFeature(Abort);
 
             var request = _httpContext.Request;
-            request.Protocol = "HTTP/1.1";
+            request.Protocol = HttpProtocol.Http11;
             request.Method = HttpMethods.Get;
 
             _requestPipe = new Pipe();
@@ -98,7 +98,7 @@ namespace Microsoft.AspNetCore.TestHost
             async Task RunRequestAsync()
             {
                 // HTTP/2 specific features must be added after the request has been configured.
-                if (string.Equals("HTTP/2", _httpContext.Request.Protocol, StringComparison.OrdinalIgnoreCase))
+                if (HttpProtocol.IsHttp2(_httpContext.Request.Protocol))
                 {
                     _httpContext.Features.Set<IHttpResetFeature>(this);
                 }

+ 1 - 1
src/Hosting/TestHost/src/RequestFeature.cs

@@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.TestHost
             Method = "GET";
             Path = "";
             PathBase = "";
-            Protocol = "HTTP/1.1";
+            Protocol = HttpProtocol.Http11;
             QueryString = "";
             Scheme = "http";
         }

+ 2 - 2
src/Hosting/TestHost/test/ClientHandlerTests.cs

@@ -27,7 +27,7 @@ namespace Microsoft.AspNetCore.TestHost
             var handler = new ClientHandler(new PathString("/A/Path/"), new DummyApplication(context =>
             {
                 // TODO: Assert.True(context.RequestAborted.CanBeCanceled);
-                Assert.Equal("HTTP/1.1", context.Request.Protocol);
+                Assert.Equal(HttpProtocol.Http11, context.Request.Protocol);
                 Assert.Equal("GET", context.Request.Method);
                 Assert.Equal("https", context.Request.Scheme);
                 Assert.Equal("/A/Path", context.Request.PathBase.Value);
@@ -53,7 +53,7 @@ namespace Microsoft.AspNetCore.TestHost
             var handler = new ClientHandler(new PathString("/A/Path/"), new InspectingApplication(features =>
             {
                 Assert.True(features.Get<IHttpRequestLifetimeFeature>().RequestAborted.CanBeCanceled);
-                Assert.Equal("HTTP/1.1", features.Get<IHttpRequestFeature>().Protocol);
+                Assert.Equal(HttpProtocol.Http11, features.Get<IHttpRequestFeature>().Protocol);
                 Assert.Equal("GET", features.Get<IHttpRequestFeature>().Method);
                 Assert.Equal("https", features.Get<IHttpRequestFeature>().Scheme);
                 Assert.Equal("/A/Path", features.Get<IHttpRequestFeature>().PathBase);

+ 1 - 1
src/Hosting/TestHost/test/HttpContextBuilderTests.cs

@@ -33,7 +33,7 @@ namespace Microsoft.AspNetCore.TestHost
             });
 
             Assert.True(context.RequestAborted.CanBeCanceled);
-            Assert.Equal("HTTP/1.1", context.Request.Protocol);
+            Assert.Equal(HttpProtocol.Http11, context.Request.Protocol);
             Assert.Equal("POST", context.Request.Method);
             Assert.Equal("https", context.Request.Scheme);
             Assert.Equal("example.com", context.Request.Host.Value);

+ 12 - 0
src/Http/Http.Abstractions/ref/Microsoft.AspNetCore.Http.Abstractions.netcoreapp.cs

@@ -250,6 +250,18 @@ namespace Microsoft.AspNetCore.Http
         public static bool IsPut(string method) { throw null; }
         public static bool IsTrace(string method) { throw null; }
     }
+    public static partial class HttpProtocol
+    {
+        public static readonly string Http10;
+        public static readonly string Http11;
+        public static readonly string Http2;
+        public static readonly string Http3;
+        public static string GetHttpProtocol(System.Version version) { throw null; }
+        public static bool IsHttp10(string protocol) { throw null; }
+        public static bool IsHttp11(string protocol) { throw null; }
+        public static bool IsHttp2(string protocol) { throw null; }
+        public static bool IsHttp3(string protocol) { throw null; }
+    }
     public abstract partial class HttpRequest
     {
         protected HttpRequest() { }

+ 96 - 0
src/Http/Http.Abstractions/src/HttpProtocol.cs

@@ -0,0 +1,96 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+
+namespace Microsoft.AspNetCore.Http
+{
+    /// <summary>
+    /// Contains methods to verify the request protocol version of an HTTP request. 
+    /// </summary>
+    public static class HttpProtocol
+    {
+        // 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.
+
+        // Please do NOT change these to 'const'
+        public static readonly string Http10 = "HTTP/1.0";
+        public static readonly string Http11 = "HTTP/1.1";
+        public static readonly string Http2 = "HTTP/2";
+        public static readonly string Http3 = "HTTP/3";
+
+        /// <summary>
+        /// Returns a value that indicates if the HTTP request protocol is HTTP/1.0. 
+        /// </summary>
+        /// <param name="protocol">The HTTP request protocol.</param>
+        /// <returns>
+        /// <see langword="true" /> if the protocol is HTTP/1.0; otherwise, <see langword="false" />.
+        /// </returns>
+        public static bool IsHttp10(string protocol)
+        {
+            return object.ReferenceEquals(Http10, protocol) || StringComparer.OrdinalIgnoreCase.Equals(Http10, protocol);
+        }
+
+        /// <summary>
+        /// Returns a value that indicates if the HTTP request protocol is HTTP/1.1. 
+        /// </summary>
+        /// <param name="protocol">The HTTP request protocol.</param>
+        /// <returns>
+        /// <see langword="true" /> if the protocol is HTTP/1.1; otherwise, <see langword="false" />.
+        /// </returns>
+        public static bool IsHttp11(string protocol)
+        {
+            return object.ReferenceEquals(Http11, protocol) || StringComparer.OrdinalIgnoreCase.Equals(Http11, protocol);
+        }
+
+        /// <summary>
+        /// Returns a value that indicates if the HTTP request protocol is HTTP/2. 
+        /// </summary>
+        /// <param name="protocol">The HTTP request protocol.</param>
+        /// <returns>
+        /// <see langword="true" /> if the protocol is HTTP/2; otherwise, <see langword="false" />.
+        /// </returns>
+        public static bool IsHttp2(string protocol)
+        {
+            return object.ReferenceEquals(Http2, protocol) || StringComparer.OrdinalIgnoreCase.Equals(Http2, protocol);
+        }
+
+        /// <summary>
+        /// Returns a value that indicates if the HTTP request protocol is HTTP/3. 
+        /// </summary>
+        /// <param name="protocol">The HTTP request protocol.</param>
+        /// <returns>
+        /// <see langword="true" /> if the protocol is HTTP/3; otherwise, <see langword="false" />.
+        /// </returns>
+        public static bool IsHttp3(string protocol)
+        {
+            return object.ReferenceEquals(Http3, protocol) || StringComparer.OrdinalIgnoreCase.Equals(Http3, protocol);
+        }
+
+        /// <summary>
+        /// Gets the HTTP request protocol for the specified <see cref="Version"/>.
+        /// </summary>
+        /// <param name="version">The version.</param>
+        /// <returns>A HTTP request protocol.</returns>
+        public static string GetHttpProtocol(Version version)
+        {
+            if (version == null)
+            {
+                throw new ArgumentNullException(nameof(version));
+            }
+
+            return version switch
+            {
+                { Major: 3, Minor: 0 } => Http3,
+                { Major: 2, Minor: 0 } => Http2,
+                { Major: 1, Minor: 1 } => Http11,
+                { Major: 1, Minor: 0 } => Http10,
+                _ => throw new ArgumentOutOfRangeException(nameof(version), "Version doesn't map to a known HTTP protocol.")
+            };
+        }
+    }
+}

+ 117 - 0
src/Http/Http.Abstractions/test/HttpProtocolTests.cs

@@ -0,0 +1,117 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using Xunit;
+
+namespace Microsoft.AspNetCore.Http.Abstractions
+{
+    public class HttpProtocolTests
+    {
+        [Fact]
+        public void Http3_Success()
+        {
+            Assert.Equal("HTTP/3", HttpProtocol.Http3);
+        }
+
+        [Theory]
+        [InlineData("HTTP/3", true)]
+        [InlineData("http/3", true)]
+        [InlineData("HTTP/1.1", false)]
+        [InlineData("HTTP/3.0", false)]
+        [InlineData("HTTP/1", false)]
+        [InlineData(" HTTP/3", false)]
+        [InlineData("HTTP/3 ", false)]
+        public void IsHttp3_Success(string protocol, bool match)
+        {
+            Assert.Equal(match, HttpProtocol.IsHttp3(protocol));
+        }
+
+        [Fact]
+        public void Http2_Success()
+        {
+            Assert.Equal("HTTP/2", HttpProtocol.Http2);
+        }
+
+        [Theory]
+        [InlineData("HTTP/2", true)]
+        [InlineData("http/2", true)]
+        [InlineData("HTTP/1.1", false)]
+        [InlineData("HTTP/2.0", false)]
+        [InlineData("HTTP/1", false)]
+        [InlineData(" HTTP/2", false)]
+        [InlineData("HTTP/2 ", false)]
+        public void IsHttp2_Success(string protocol, bool match)
+        {
+            Assert.Equal(match, HttpProtocol.IsHttp2(protocol));
+        }
+
+        [Fact]
+        public void Http11_Success()
+        {
+            Assert.Equal("HTTP/1.1", HttpProtocol.Http11);
+        }
+
+        [Theory]
+        [InlineData("HTTP/1.1", true)]
+        [InlineData("http/1.1", true)]
+        [InlineData("HTTP/2", false)]
+        [InlineData("HTTP/1.0", false)]
+        [InlineData("HTTP/1", false)]
+        [InlineData(" HTTP/1.1", false)]
+        [InlineData("HTTP/1.1 ", false)]
+        public void IsHttp11_Success(string protocol, bool match)
+        {
+            Assert.Equal(match, HttpProtocol.IsHttp11(protocol));
+        }
+
+        [Fact]
+        public void Http10_Success()
+        {
+            Assert.Equal("HTTP/1.0", HttpProtocol.Http10);
+        }
+
+        [Theory]
+        [InlineData("HTTP/1.0", true)]
+        [InlineData("http/1.0", true)]
+        [InlineData("HTTP/2", false)]
+        [InlineData("HTTP/1.1", false)]
+        [InlineData("HTTP/1", false)]
+        [InlineData(" HTTP/1.0", false)]
+        [InlineData("HTTP/1.0 ", false)]
+        public void IsHttp10_Success(string protocol, bool match)
+        {
+            Assert.Equal(match, HttpProtocol.IsHttp10(protocol));
+        }
+
+        public static TheoryData<Version, string> s_ValidData = new TheoryData<Version, string>
+        {
+            { new Version(3, 0), "HTTP/3" },
+            { new Version(2, 0), "HTTP/2" },
+            { new Version(1, 1), "HTTP/1.1" },
+            { new Version(1, 0), "HTTP/1.0" }
+        };
+
+        [Theory]
+        [MemberData(nameof(s_ValidData))]
+        public void GetHttpProtocol_CorrectIETFVersion(Version version, string expected)
+        {
+            var actual = HttpProtocol.GetHttpProtocol(version);
+
+            Assert.Equal(expected, actual);
+        }
+
+        public static TheoryData<Version> s_InvalidData = new TheoryData<Version>
+        {
+            { new Version(0, 3) },
+            { new Version(2, 1) }
+        };
+
+        [Theory]
+        [MemberData(nameof(s_InvalidData))]
+        public void GetHttpProtocol_ThrowErrorForUnknownVersion(Version version)
+        {
+            Assert.Throws<ArgumentOutOfRangeException>(() => HttpProtocol.GetHttpProtocol(version));
+        }
+    }
+}

+ 5 - 5
src/Security/Authentication/Negotiate/src/NegotiateHandler.cs

@@ -57,7 +57,7 @@ namespace Microsoft.AspNetCore.Authentication.Negotiate
         /// <returns></returns>
         protected override Task<object> CreateEventsAsync() => Task.FromResult<object>(new NegotiateEvents());
 
-        private bool IsHttp2 => string.Equals("HTTP/2", Request.Protocol, StringComparison.OrdinalIgnoreCase);
+        private bool IsSupportedProtocol => HttpProtocol.IsHttp11(Request.Protocol) || HttpProtocol.IsHttp10(Request.Protocol);
 
         /// <summary>
         /// Intercepts incomplete Negotiate authentication handshakes and continues or completes them.
@@ -80,10 +80,10 @@ namespace Microsoft.AspNetCore.Authentication.Negotiate
 
                 _requestProcessed = true;
 
-                if (IsHttp2)
+                if (!IsSupportedProtocol)
                 {
-                    // HTTP/2 is not supported. Do not throw because this may be running on a server that supports
-                    // both HTTP/1 and HTTP/2.
+                    // HTTP/1.0 and HTTP/1.1 are supported. Do not throw because this may be running on a server that supports
+                    // additional protocols.
                     return false;
                 }
 
@@ -291,7 +291,7 @@ namespace Microsoft.AspNetCore.Authentication.Negotiate
                 throw new InvalidOperationException("AuthenticateAsync must not be called before the UseAuthentication middleware runs.");
             }
 
-            if (IsHttp2)
+            if (!IsSupportedProtocol)
             {
                 // Not supported. We don't throw because Negotiate may be set as the default auth
                 // handler on a server that's running HTTP/1 and HTTP/2. We'll challenge HTTP/2 requests

+ 1 - 1
src/Servers/HttpSys/src/FeatureContext.cs

@@ -181,7 +181,7 @@ namespace Microsoft.AspNetCore.Server.HttpSys
             {
                 if (IsNotInitialized(Fields.Protocol))
                 {
-                    _httpProtocolVersion = Request.ProtocolVersion.GetHttpProtocolVersion();
+                    _httpProtocolVersion = HttpProtocol.GetHttpProtocol(Request.ProtocolVersion);
                     SetInitialized(Fields.Protocol);
                 }
                 return _httpProtocolVersion;

+ 1 - 1
src/Servers/IIS/IIS/src/Core/IISHttpContext.FeatureCollection.cs

@@ -87,7 +87,7 @@ namespace Microsoft.AspNetCore.Server.IIS.Core
 
         string IHttpRequestFeature.Protocol
         {
-            get => _httpProtocolVersion ??= HttpVersion.GetHttpProtocolVersion();
+            get => _httpProtocolVersion ??= HttpProtocol.GetHttpProtocol(HttpVersion);
             set => _httpProtocolVersion = value;
         }
 

+ 24 - 24
src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.cs

@@ -146,21 +146,21 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
         {
             get
             {
-                if (_httpVersion == Http.HttpVersion.Http11)
+                if (_httpVersion == Http.HttpVersion.Http3)
                 {
-                    return HttpUtilities.Http11Version;
+                    return AspNetCore.Http.HttpProtocol.Http3;
                 }
-                if (_httpVersion == Http.HttpVersion.Http10)
+                if (_httpVersion == Http.HttpVersion.Http2)
                 {
-                    return HttpUtilities.Http10Version;
+                    return AspNetCore.Http.HttpProtocol.Http2;
                 }
-                if (_httpVersion == Http.HttpVersion.Http2)
+                if (_httpVersion == Http.HttpVersion.Http11)
                 {
-                    return HttpUtilities.Http2Version;
+                    return AspNetCore.Http.HttpProtocol.Http11;
                 }
-                if (_httpVersion == Http.HttpVersion.Http3)
+                if (_httpVersion == Http.HttpVersion.Http10)
                 {
-                    return HttpUtilities.Http3Version;
+                    return AspNetCore.Http.HttpProtocol.Http10;
                 }
 
                 return string.Empty;
@@ -171,21 +171,21 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
             {
                 // GetKnownVersion returns versions which ReferenceEquals interned string
                 // As most common path, check for this only in fast-path and inline
-                if (ReferenceEquals(value, HttpUtilities.Http11Version))
+                if (ReferenceEquals(value, AspNetCore.Http.HttpProtocol.Http3))
                 {
-                    _httpVersion = Http.HttpVersion.Http11;
+                    _httpVersion = Http.HttpVersion.Http3;
                 }
-                else if (ReferenceEquals(value, HttpUtilities.Http10Version))
+                else if (ReferenceEquals(value, AspNetCore.Http.HttpProtocol.Http2))
                 {
-                    _httpVersion = Http.HttpVersion.Http10;
+                    _httpVersion = Http.HttpVersion.Http2;
                 }
-                else if (ReferenceEquals(value, HttpUtilities.Http2Version))
+                else if (ReferenceEquals(value, AspNetCore.Http.HttpProtocol.Http11))
                 {
-                    _httpVersion = Http.HttpVersion.Http2;
+                    _httpVersion = Http.HttpVersion.Http11;
                 }
-                else if (ReferenceEquals(value, HttpUtilities.Http3Version))
+                else if (ReferenceEquals(value, AspNetCore.Http.HttpProtocol.Http10))
                 {
-                    _httpVersion = Http.HttpVersion.Http3;
+                    _httpVersion = Http.HttpVersion.Http10;
                 }
                 else
                 {
@@ -197,21 +197,21 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
         [MethodImpl(MethodImplOptions.NoInlining)]
         private void HttpVersionSetSlow(string value)
         {
-            if (value == HttpUtilities.Http11Version)
+            if (AspNetCore.Http.HttpProtocol.IsHttp3(value))
             {
-                _httpVersion = Http.HttpVersion.Http11;
+                _httpVersion = Http.HttpVersion.Http3;
             }
-            else if (value == HttpUtilities.Http10Version)
+            else if (AspNetCore.Http.HttpProtocol.IsHttp2(value))
             {
-                _httpVersion = Http.HttpVersion.Http10;
+                _httpVersion = Http.HttpVersion.Http2;
             }
-            else if (value == HttpUtilities.Http2Version)
+            else if (AspNetCore.Http.HttpProtocol.IsHttp11(value))
             {
-                _httpVersion = Http.HttpVersion.Http2;
+                _httpVersion = Http.HttpVersion.Http11;
             }
-            else if (value == HttpUtilities.Http3Version)
+            else if (AspNetCore.Http.HttpProtocol.IsHttp10(value))
             {
-                _httpVersion = Http.HttpVersion.Http3;
+                _httpVersion = Http.HttpVersion.Http10;
             }
             else
             {

+ 14 - 10
src/Servers/Kestrel/Core/src/Internal/Infrastructure/HttpUtilities.cs

@@ -12,11 +12,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
 {
     internal static partial class HttpUtilities
     {
-        public const string Http10Version = "HTTP/1.0";
-        public const string Http11Version = "HTTP/1.1";
-        public const string Http2Version = "HTTP/2";
-        public const string Http3Version = "HTTP/3";
-
         public const string HttpUriScheme = "http://";
         public const string HttpsUriScheme = "https://";
 
@@ -429,13 +424,22 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
 
         public static string VersionToString(HttpVersion httpVersion)
         {
-            return httpVersion switch
-            {
-                HttpVersion.Http10 => Http10Version,
-                HttpVersion.Http11 => Http11Version,
-                _ => null,
+            switch (httpVersion)
+            {
+                case HttpVersion.Http10:
+                    return AspNetCore.Http.HttpProtocol.Http10;
+                case HttpVersion.Http11:
+                    return AspNetCore.Http.HttpProtocol.Http11;
+                case HttpVersion.Http2:
+                    return AspNetCore.Http.HttpProtocol.Http2;
+                case HttpVersion.Http3:
+                    return AspNetCore.Http.HttpProtocol.Http3;
+                default:
+                    Debug.Fail("Unexpected HttpVersion: " + httpVersion);
+                    return null;
             };
         }
+
         public static string MethodToString(HttpMethod method)
         {
             var methodIndex = (int)method;

+ 2 - 2
src/Servers/Kestrel/Core/test/HttpUtilitiesTest.cs

@@ -52,8 +52,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
         }
 
         [Theory]
-        [InlineData("HTTP/1.0\r", true, HttpUtilities.Http10Version, (int)HttpVersion.Http10)]
-        [InlineData("HTTP/1.1\r", true, HttpUtilities.Http11Version, (int)HttpVersion.Http11)]
+        [InlineData("HTTP/1.0\r", true, "HTTP/1.0", (int)HttpVersion.Http10)]
+        [InlineData("HTTP/1.1\r", true, "HTTP/1.1", (int)HttpVersion.Http11)]
         [InlineData("HTTP/3.0\r", false, null, (int)HttpVersion.Unknown)]
         [InlineData("http/1.0\r", false, null, (int)HttpVersion.Unknown)]
         [InlineData("http/1.1\r", false, null, (int)HttpVersion.Unknown)]

+ 1 - 1
src/Servers/Kestrel/Transport.Libuv/test/LibuvTransportTests.cs

@@ -184,7 +184,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests
                 return context.Response.WriteAsync("Hello World");
             });
 
-            listenOptions.UseHttpServer(serviceContext, testApplication, HttpProtocols.Http1);
+            listenOptions.UseHttpServer(serviceContext, testApplication, Core.HttpProtocols.Http1);
 
             var transportContext = new TestLibuvTransportContext
             {

+ 1 - 1
src/Servers/Kestrel/test/Interop.FunctionalTests/HttpClientHttp2InteropTests.cs

@@ -1,4 +1,4 @@
-// Copyright (c) .NET Foundation. All rights reserved.
+// Copyright (c) .NET Foundation. All rights reserved.
 // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
 
 using System;

+ 0 - 18
src/Shared/HttpSys/Extensions.cs

@@ -1,18 +0,0 @@
-// Copyright (c) .NET Foundation. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-
-using System;
-
-namespace Microsoft.AspNetCore.HttpSys.Internal
-{
-    internal static class Extensions
-    {
-        public static string GetHttpProtocolVersion(this Version version) => version switch
-        {
-            { Major: 2, Minor: 0 } => "HTTP/2",
-            { Major: 1, Minor: 1 } => "HTTP/1.1",
-            { Major: 1, Minor: 0 } => "HTTP/1.0",
-            _ => "HTTP/" + version.ToString(2)
-        };
-    }
-}

+ 3 - 0
src/Shared/startvs.cmd

@@ -0,0 +1,3 @@
+@ECHO OFF
+
+%~dp0..\..\startvs.cmd %~dp0Shared.sln

+ 0 - 29
src/Shared/test/Shared.Tests/HttpSysGetHttpProtocolVersionTest.cs

@@ -1,29 +0,0 @@
-// Copyright (c) .NET Foundation. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-
-using System;
-using Xunit;
-
-namespace Microsoft.AspNetCore.HttpSys.Internal
-{
-    public class HttpSysGetHttpProtocolVersionTest
-    {
-        public static TheoryData<Version, string> s_data = new TheoryData<Version, string>
-        {
-            { new Version(2, 0), "HTTP/2" },
-            { new Version(1, 1), "HTTP/1.1" },
-            { new Version(1, 0), "HTTP/1.0" },
-            { new Version(0, 3), "HTTP/0.3" },
-            { new Version(2, 1), "HTTP/2.1" }
-        };
-
-        [Theory]
-        [MemberData(nameof(s_data))]
-        public void GetHttpProtocolVersion_CorrectIETFVersion(Version version, string expected)
-        {
-            var actual = version.GetHttpProtocolVersion();
-
-            Assert.Equal(expected, actual);
-        }
-    }
-}