Automatically chunk and set 0 Content-Length for non keep-alive responses

This commit is contained in:
Stephen Halter 2016-08-10 16:58:17 -07:00
parent 5f4e60bf8d
commit 16fbb94c44
4 changed files with 78 additions and 4 deletions

View File

@ -733,7 +733,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
} }
} }
if (_keepAlive && !responseHeaders.HasTransferEncoding && !responseHeaders.HasContentLength) if (!responseHeaders.HasTransferEncoding && !responseHeaders.HasContentLength)
{ {
if (appCompleted) if (appCompleted)
{ {

View File

@ -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] [Theory]
[MemberData(nameof(ConnectionFilterData))] [MemberData(nameof(ConnectionFilterData))]
public async Task ZeroLengthWritesAreIgnored(TestServiceContext testContext) public async Task ZeroLengthWritesAreIgnored(TestServiceContext testContext)

View File

@ -39,6 +39,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
"HTTP/1.1 200 OK", "HTTP/1.1 200 OK",
"Connection: close", "Connection: close",
$"Date: {testContext.DateHeaderValue}", $"Date: {testContext.DateHeaderValue}",
"Content-Length: 0",
"Server: Kestrel", "Server: Kestrel",
"", "",
""); "");

View File

@ -187,7 +187,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
IHeaderDictionary lastResponseHeaders = null; IHeaderDictionary lastResponseHeaders = null;
using (var server = new TestServer( using (var server = new TestServer(
context => async context =>
{ {
if (context.Request.Body != lastStream) if (context.Request.Body != lastStream)
{ {
@ -204,7 +204,14 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
lastResponseHeaders = context.Response.Headers; lastResponseHeaders = context.Response.Headers;
responseHeadersCount++; 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)) testContext))
{ {
@ -226,6 +233,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
"HTTP/1.1 200 OK", "HTTP/1.1 200 OK",
"Connection: close", "Connection: close",
$"Date: {testContext.DateHeaderValue}", $"Date: {testContext.DateHeaderValue}",
"Content-Length: 7",
"", "",
"Goodbye" "Goodbye"
}); });
@ -414,6 +422,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
"HTTP/1.1 200 OK", "HTTP/1.1 200 OK",
"Connection: close", "Connection: close",
$"Date: {testContext.DateHeaderValue}", $"Date: {testContext.DateHeaderValue}",
"Content-Length: 0",
"\r\n"); "\r\n");
} }
} }
@ -451,7 +460,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
[Theory] [Theory]
[MemberData(nameof(ConnectionFilterData))] [MemberData(nameof(ConnectionFilterData))]
public async Task ZeroContentLengthNotSetAutomaticallyForNonKeepAliveRequests(TestServiceContext testContext) public async Task ZeroContentLengthSetAutomaticallyForNonKeepAliveRequests(TestServiceContext testContext)
{ {
using (var server = new TestServer(EmptyApp, testContext)) using (var server = new TestServer(EmptyApp, testContext))
{ {
@ -466,6 +475,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
"HTTP/1.1 200 OK", "HTTP/1.1 200 OK",
"Connection: close", "Connection: close",
$"Date: {testContext.DateHeaderValue}", $"Date: {testContext.DateHeaderValue}",
"Content-Length: 0",
"", "",
""); "");
} }
@ -480,6 +490,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
"HTTP/1.1 200 OK", "HTTP/1.1 200 OK",
"Connection: close", "Connection: close",
$"Date: {testContext.DateHeaderValue}", $"Date: {testContext.DateHeaderValue}",
"Content-Length: 0",
"", "",
""); "");
} }