diff --git a/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Http/Frame.cs b/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Http/Frame.cs index f657864302..aad34b77dd 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Http/Frame.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Http/Frame.cs @@ -733,7 +733,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http } } - if (_keepAlive && !responseHeaders.HasTransferEncoding && !responseHeaders.HasContentLength) + if (!responseHeaders.HasTransferEncoding && !responseHeaders.HasContentLength) { if (appCompleted) { diff --git a/test/Microsoft.AspNetCore.Server.KestrelTests/ChunkedResponseTests.cs b/test/Microsoft.AspNetCore.Server.KestrelTests/ChunkedResponseTests.cs index 1427cfc90a..1f970fa9cf 100644 --- a/test/Microsoft.AspNetCore.Server.KestrelTests/ChunkedResponseTests.cs +++ b/test/Microsoft.AspNetCore.Server.KestrelTests/ChunkedResponseTests.cs @@ -61,6 +61,68 @@ namespace Microsoft.AspNetCore.Server.KestrelTests } } + [Theory] + [MemberData(nameof(ConnectionFilterData))] + public async Task ResponsesAreChunkedAutomaticallyForHttp11NonKeepAliveRequests(TestServiceContext testContext) + { + using (var server = new TestServer(async httpContext => + { + var response = httpContext.Response; + await response.Body.WriteAsync(Encoding.ASCII.GetBytes("Hello "), 0, 6); + await response.Body.WriteAsync(Encoding.ASCII.GetBytes("World!"), 0, 6); + }, testContext)) + { + using (var connection = server.CreateConnection()) + { + await connection.SendEnd( + "GET / HTTP/1.1", + "Connection: close", + "", + ""); + await connection.ReceiveEnd( + "HTTP/1.1 200 OK", + "Connection: close", + $"Date: {testContext.DateHeaderValue}", + "Transfer-Encoding: chunked", + "", + "6", + "Hello ", + "6", + "World!", + "0", + "", + ""); + } + } + } + + [Theory] + [MemberData(nameof(ConnectionFilterData))] + public async Task ResponsesAreNotChunkedAutomaticallyForHttp10Requests(TestServiceContext testContext) + { + using (var server = new TestServer(async httpContext => + { + var response = httpContext.Response; + await response.Body.WriteAsync(Encoding.ASCII.GetBytes("Hello "), 0, 6); + await response.Body.WriteAsync(Encoding.ASCII.GetBytes("World!"), 0, 6); + }, testContext)) + { + using (var connection = server.CreateConnection()) + { + await connection.SendEnd( + "GET / HTTP/1.0", + "", + ""); + await connection.ReceiveEnd( + "HTTP/1.1 200 OK", + "Connection: close", + $"Date: {testContext.DateHeaderValue}", + "", + "Hello World!"); + } + } + } + [Theory] [MemberData(nameof(ConnectionFilterData))] public async Task ZeroLengthWritesAreIgnored(TestServiceContext testContext) diff --git a/test/Microsoft.AspNetCore.Server.KestrelTests/DefaultHeaderTests.cs b/test/Microsoft.AspNetCore.Server.KestrelTests/DefaultHeaderTests.cs index a8818d80fe..964345b48a 100644 --- a/test/Microsoft.AspNetCore.Server.KestrelTests/DefaultHeaderTests.cs +++ b/test/Microsoft.AspNetCore.Server.KestrelTests/DefaultHeaderTests.cs @@ -39,6 +39,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests "HTTP/1.1 200 OK", "Connection: close", $"Date: {testContext.DateHeaderValue}", + "Content-Length: 0", "Server: Kestrel", "", ""); diff --git a/test/Microsoft.AspNetCore.Server.KestrelTests/EngineTests.cs b/test/Microsoft.AspNetCore.Server.KestrelTests/EngineTests.cs index 59f713fe41..80e59304f8 100644 --- a/test/Microsoft.AspNetCore.Server.KestrelTests/EngineTests.cs +++ b/test/Microsoft.AspNetCore.Server.KestrelTests/EngineTests.cs @@ -187,7 +187,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests IHeaderDictionary lastResponseHeaders = null; using (var server = new TestServer( - context => + async context => { if (context.Request.Body != lastStream) { @@ -204,7 +204,14 @@ namespace Microsoft.AspNetCore.Server.KestrelTests lastResponseHeaders = context.Response.Headers; responseHeadersCount++; } - return context.Request.Body.CopyToAsync(context.Response.Body); + + var ms = new MemoryStream(); + await context.Request.Body.CopyToAsync(ms); + var request = ms.ToArray(); + + context.Response.ContentLength = request.Length; + + await context.Response.Body.WriteAsync(request, 0, request.Length); }, testContext)) { @@ -226,6 +233,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests "HTTP/1.1 200 OK", "Connection: close", $"Date: {testContext.DateHeaderValue}", + "Content-Length: 7", "", "Goodbye" }); @@ -414,6 +422,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests "HTTP/1.1 200 OK", "Connection: close", $"Date: {testContext.DateHeaderValue}", + "Content-Length: 0", "\r\n"); } } @@ -451,7 +460,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests [Theory] [MemberData(nameof(ConnectionFilterData))] - public async Task ZeroContentLengthNotSetAutomaticallyForNonKeepAliveRequests(TestServiceContext testContext) + public async Task ZeroContentLengthSetAutomaticallyForNonKeepAliveRequests(TestServiceContext testContext) { using (var server = new TestServer(EmptyApp, testContext)) { @@ -466,6 +475,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests "HTTP/1.1 200 OK", "Connection: close", $"Date: {testContext.DateHeaderValue}", + "Content-Length: 0", "", ""); } @@ -480,6 +490,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests "HTTP/1.1 200 OK", "Connection: close", $"Date: {testContext.DateHeaderValue}", + "Content-Length: 0", "", ""); }