HEAD response can include Content-Length header.
This commit is contained in:
parent
ce6e65b1d7
commit
ffc3eb3afd
|
|
@ -617,6 +617,21 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
|
|||
_responseBytesWritten += count;
|
||||
}
|
||||
|
||||
protected void VerifyResponseContentLength()
|
||||
{
|
||||
var responseHeaders = FrameResponseHeaders;
|
||||
|
||||
if (!HttpMethods.IsHead(Method) &&
|
||||
!responseHeaders.HasTransferEncoding &&
|
||||
responseHeaders.HeaderContentLengthValue.HasValue &&
|
||||
_responseBytesWritten < responseHeaders.HeaderContentLengthValue.Value)
|
||||
{
|
||||
_keepAlive = false;
|
||||
ReportApplicationError(new InvalidOperationException(
|
||||
$"Response Content-Length mismatch: too few bytes written ({_responseBytesWritten} of {responseHeaders.HeaderContentLengthValue.Value})."));
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteChunked(ArraySegment<byte> data)
|
||||
{
|
||||
SocketOutput.Write(data, chunk: true);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using System;
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Hosting.Server;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
|
||||
|
|
@ -92,16 +93,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
|
|||
try
|
||||
{
|
||||
await _application.ProcessRequestAsync(context).ConfigureAwait(false);
|
||||
|
||||
var responseHeaders = FrameResponseHeaders;
|
||||
if (!responseHeaders.HasTransferEncoding &&
|
||||
responseHeaders.HasContentLength &&
|
||||
_responseBytesWritten < responseHeaders.HeaderContentLengthValue.Value)
|
||||
{
|
||||
_keepAlive = false;
|
||||
ReportApplicationError(new InvalidOperationException(
|
||||
$"Response Content-Length mismatch: too few bytes written ({_responseBytesWritten} of {responseHeaders.HeaderContentLengthValue.Value})."));
|
||||
}
|
||||
VerifyResponseContentLength();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -607,6 +607,62 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|||
Assert.Equal(0, testLogger.ApplicationErrorsLogged);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HeadResponseCanContainContentLengthHeader()
|
||||
{
|
||||
var testLogger = new TestApplicationErrorLogger();
|
||||
var serviceContext = new TestServiceContext { Log = new TestKestrelTrace(testLogger) };
|
||||
|
||||
using (var server = new TestServer(httpContext =>
|
||||
{
|
||||
httpContext.Response.ContentLength = 42;
|
||||
return TaskCache.CompletedTask;
|
||||
}, serviceContext))
|
||||
{
|
||||
using (var connection = server.CreateConnection())
|
||||
{
|
||||
await connection.SendEnd(
|
||||
"HEAD / HTTP/1.1",
|
||||
"",
|
||||
"");
|
||||
await connection.ReceiveEnd(
|
||||
$"HTTP/1.1 200 OK",
|
||||
$"Date: {server.Context.DateHeaderValue}",
|
||||
"Content-Length: 42",
|
||||
"",
|
||||
"");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HeadResponseCanContainContentLengthHeaderButBodyNotWritten()
|
||||
{
|
||||
var testLogger = new TestApplicationErrorLogger();
|
||||
var serviceContext = new TestServiceContext { Log = new TestKestrelTrace(testLogger) };
|
||||
|
||||
using (var server = new TestServer(async httpContext =>
|
||||
{
|
||||
httpContext.Response.ContentLength = 12;
|
||||
await httpContext.Response.WriteAsync("hello, world");
|
||||
}, serviceContext))
|
||||
{
|
||||
using (var connection = server.CreateConnection())
|
||||
{
|
||||
await connection.SendEnd(
|
||||
"HEAD / HTTP/1.1",
|
||||
"",
|
||||
"");
|
||||
await connection.ReceiveEnd(
|
||||
$"HTTP/1.1 200 OK",
|
||||
$"Date: {server.Context.DateHeaderValue}",
|
||||
"Content-Length: 12",
|
||||
"",
|
||||
"");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static TheoryData<string, StringValues, string> NullHeaderData
|
||||
{
|
||||
get
|
||||
|
|
|
|||
Loading…
Reference in New Issue