diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.FeatureCollection.cs b/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.FeatureCollection.cs index 88ae92e0c0..8841be09fa 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.FeatureCollection.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.FeatureCollection.cs @@ -37,8 +37,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http string IHttpRequestFeature.Protocol { - get => HttpVersion; - set => HttpVersion = value; + get => _httpProtocol ??= HttpVersion; + set => _httpProtocol = value; } string IHttpRequestFeature.Scheme diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.cs b/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.cs index cc4377af1d..2110a1528f 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.cs @@ -57,6 +57,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http private BadHttpRequestException _requestRejectedException; protected HttpVersion _httpVersion; + // This should only be used by the application, not the server. This is settable on HttpRequest but we don't want that to affect + // how Kestrel processes requests/responses. + private string _httpProtocol; private string _requestId; private int _requestHeadersParsed; @@ -351,6 +354,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http RawTarget = null; QueryString = null; _httpVersion = Http.HttpVersion.Unknown; + _httpProtocol = null; _statusCode = StatusCodes.Status200OK; _reasonPhrase = null; diff --git a/src/Servers/Kestrel/test/InMemory.FunctionalTests/ChunkedResponseTests.cs b/src/Servers/Kestrel/test/InMemory.FunctionalTests/ChunkedResponseTests.cs index 3d109476a5..f279141a7d 100644 --- a/src/Servers/Kestrel/test/InMemory.FunctionalTests/ChunkedResponseTests.cs +++ b/src/Servers/Kestrel/test/InMemory.FunctionalTests/ChunkedResponseTests.cs @@ -78,6 +78,42 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests } } + [Fact] + public async Task IgnoresChangesToHttpProtocol() + { + var testContext = new TestServiceContext(LoggerFactory); + + await using (var server = new TestServer(async httpContext => + { + httpContext.Request.Protocol = "HTTP/2"; // Doesn't support chunking. This change should be ignored. + var response = httpContext.Response; + await response.BodyWriter.WriteAsync(new Memory(Encoding.ASCII.GetBytes("Hello "), 0, 6)); + await response.BodyWriter.WriteAsync(new Memory(Encoding.ASCII.GetBytes("World!"), 0, 6)); + }, testContext)) + { + using (var connection = server.CreateConnection()) + { + await connection.Send( + "GET / HTTP/1.1", + "Host:", + "", + ""); + await connection.Receive( + "HTTP/1.1 200 OK", + $"Date: {testContext.DateHeaderValue}", + "Transfer-Encoding: chunked", + "", + "6", + "Hello ", + "6", + "World!", + "0", + "", + ""); + } + } + } + [Fact] public async Task ResponsesAreChunkedAutomaticallyForHttp11NonKeepAliveRequests() {