Don't automatically set Content-Length: 0 in some circumstances
- When in response to a HEAD Request - For 101, 204, 205 and 304 responses - For non keep-alive connections
This commit is contained in:
parent
69759231ff
commit
2642c84bf9
|
|
@ -494,26 +494,33 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (appCompleted && !hasTransferEncoding && !hasContentLength)
|
|
||||||
{
|
|
||||||
// Since the app has completed and we are only now generating
|
|
||||||
// the headers we can safely set the Content-Length to 0.
|
|
||||||
writer.Write("Content-Length: 0\r\n");
|
|
||||||
hasContentLength = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_keepAlive && !hasTransferEncoding && !hasContentLength)
|
if (_keepAlive && !hasTransferEncoding && !hasContentLength)
|
||||||
{
|
{
|
||||||
if (HttpVersion == "HTTP/1.1")
|
if (appCompleted)
|
||||||
{
|
{
|
||||||
_autoChunk = true;
|
// Don't set the Content-Length or Transfer-Encoding headers
|
||||||
writer.Write("Transfer-Encoding: chunked\r\n");
|
// automatically for HEAD requests or 101, 204, 205, 304 responses.
|
||||||
|
if (Method != "HEAD" && StatusCanHaveBody(StatusCode))
|
||||||
|
{
|
||||||
|
// Since the app has completed and we are only now generating
|
||||||
|
// the headers we can safely set the Content-Length to 0.
|
||||||
|
writer.Write("Content-Length: 0\r\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_keepAlive = false;
|
if (HttpVersion == "HTTP/1.1")
|
||||||
|
{
|
||||||
|
_autoChunk = true;
|
||||||
|
writer.Write("Transfer-Encoding: chunked\r\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_keepAlive = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_keepAlive == false && hasConnection == false && HttpVersion == "HTTP/1.1")
|
if (_keepAlive == false && hasConnection == false && HttpVersion == "HTTP/1.1")
|
||||||
{
|
{
|
||||||
writer.Write("Connection: close\r\n\r\n");
|
writer.Write("Connection: close\r\n\r\n");
|
||||||
|
|
@ -673,5 +680,14 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
{
|
{
|
||||||
_requestHeaders.Append(keyBytes, keyOffset, keyLength, value);
|
_requestHeaders.Append(keyBytes, keyOffset, keyLength, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool StatusCanHaveBody(int statusCode)
|
||||||
|
{
|
||||||
|
// List of status codes taken from Microsoft.Net.Http.Server.Response
|
||||||
|
return statusCode != 101 &&
|
||||||
|
statusCode != 204 &&
|
||||||
|
statusCode != 205 &&
|
||||||
|
statusCode != 304;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,12 @@ namespace Microsoft.AspNet.Server.KestrelTests
|
||||||
await frame.ResponseBody.WriteAsync(bytes, 0, bytes.Length);
|
await frame.ResponseBody.WriteAsync(bytes, 0, bytes.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Task EmptyApp(Frame frame)
|
||||||
|
{
|
||||||
|
frame.ResponseHeaders.Clear();
|
||||||
|
return Task.FromResult<object>(null);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void EngineCanStartAndStop()
|
public void EngineCanStartAndStop()
|
||||||
{
|
{
|
||||||
|
|
@ -370,28 +376,132 @@ namespace Microsoft.AspNet.Server.KestrelTests
|
||||||
"\r\n");
|
"\r\n");
|
||||||
await connection.ReceiveEnd(
|
await connection.ReceiveEnd(
|
||||||
"HTTP/1.0 200 OK",
|
"HTTP/1.0 200 OK",
|
||||||
"Content-Length: 0",
|
|
||||||
"\r\n");
|
"\r\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task EmptyResponseBodyHandledCorrectlyWithoutAnyWrites()
|
public async Task ZeroContentLengthSetAutomaticallyAfterNoWrites()
|
||||||
{
|
{
|
||||||
using (var server = new TestServer(frame =>
|
using (var server = new TestServer(EmptyApp))
|
||||||
{
|
|
||||||
frame.ResponseHeaders.Clear();
|
|
||||||
return Task.FromResult<object>(null);
|
|
||||||
}))
|
|
||||||
{
|
{
|
||||||
using (var connection = new TestConnection())
|
using (var connection = new TestConnection())
|
||||||
{
|
{
|
||||||
await connection.SendEnd(
|
await connection.SendEnd(
|
||||||
"GET / HTTP/1.1",
|
"GET / HTTP/1.1",
|
||||||
"",
|
"",
|
||||||
|
"GET / HTTP/1.0",
|
||||||
|
"Connection: keep-alive",
|
||||||
|
"",
|
||||||
"");
|
"");
|
||||||
await connection.ReceiveEnd(
|
await connection.ReceiveEnd(
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
"Content-Length: 0",
|
||||||
|
"",
|
||||||
|
"HTTP/1.0 200 OK",
|
||||||
|
"Content-Length: 0",
|
||||||
|
"Connection: keep-alive",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ZeroContentLengthNotSetAutomaticallyForNonKeepAliveRequests()
|
||||||
|
{
|
||||||
|
using (var server = new TestServer(EmptyApp))
|
||||||
|
{
|
||||||
|
using (var connection = new TestConnection())
|
||||||
|
{
|
||||||
|
await connection.SendEnd(
|
||||||
|
"GET / HTTP/1.1",
|
||||||
|
"Connection: close",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
await connection.ReceiveEnd(
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
"Connection: close",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var connection = new TestConnection())
|
||||||
|
{
|
||||||
|
await connection.SendEnd(
|
||||||
|
"GET / HTTP/1.0",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
await connection.ReceiveEnd(
|
||||||
|
"HTTP/1.0 200 OK",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ZeroContentLengthNotSetAutomaticallyForHeadRequests()
|
||||||
|
{
|
||||||
|
using (var server = new TestServer(EmptyApp))
|
||||||
|
{
|
||||||
|
using (var connection = new TestConnection())
|
||||||
|
{
|
||||||
|
await connection.SendEnd(
|
||||||
|
"HEAD / HTTP/1.1",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
await connection.ReceiveEnd(
|
||||||
|
"HTTP/1.1 200 OK",
|
||||||
|
"",
|
||||||
|
"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ZeroContentLengthNotSetAutomaticallyForCertainStatusCodes()
|
||||||
|
{
|
||||||
|
using (var server = new TestServer(async frame =>
|
||||||
|
{
|
||||||
|
frame.ResponseHeaders.Clear();
|
||||||
|
|
||||||
|
using (var reader = new StreamReader(frame.RequestBody, Encoding.ASCII))
|
||||||
|
{
|
||||||
|
var statusString = await reader.ReadLineAsync();
|
||||||
|
frame.StatusCode = int.Parse(statusString);
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
{
|
||||||
|
using (var connection = new TestConnection())
|
||||||
|
{
|
||||||
|
await connection.SendEnd(
|
||||||
|
"POST / HTTP/1.1",
|
||||||
|
"Content-Length: 3",
|
||||||
|
"",
|
||||||
|
"101POST / HTTP/1.1",
|
||||||
|
"Content-Length: 3",
|
||||||
|
"",
|
||||||
|
"204POST / HTTP/1.1",
|
||||||
|
"Content-Length: 3",
|
||||||
|
"",
|
||||||
|
"205POST / HTTP/1.1",
|
||||||
|
"Content-Length: 3",
|
||||||
|
"",
|
||||||
|
"304POST / HTTP/1.1",
|
||||||
|
"Content-Length: 3",
|
||||||
|
"",
|
||||||
|
"200");
|
||||||
|
await connection.ReceiveEnd(
|
||||||
|
"HTTP/1.1 101 Switching Protocols",
|
||||||
|
"",
|
||||||
|
"HTTP/1.1 204 No Content",
|
||||||
|
"",
|
||||||
|
"HTTP/1.1 205 Reset Content",
|
||||||
|
"",
|
||||||
|
"HTTP/1.1 304 Not Modified",
|
||||||
|
"",
|
||||||
"HTTP/1.1 200 OK",
|
"HTTP/1.1 200 OK",
|
||||||
"Content-Length: 0",
|
"Content-Length: 0",
|
||||||
"",
|
"",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue