Skip to content
This repository was archived by the owner on Dec 18, 2018. It is now read-only.

Commit db1b445

Browse files
author
Cesar Blum Silveira
committed
More feedback.
- Log writes on responses to HEAD requests only once.
1 parent 4360f5d commit db1b445

File tree

3 files changed

+58
-10
lines changed

3 files changed

+58
-10
lines changed

src/Microsoft.AspNetCore.Server.Kestrel/Internal/Http/Frame.cs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ public abstract partial class Frame : IFrameControl
7575
protected readonly long _keepAliveMilliseconds;
7676
private readonly long _requestHeadersTimeoutMilliseconds;
7777

78+
private int _responseBytesWritten;
79+
7880
public Frame(ConnectionContext context)
7981
{
8082
ConnectionContext = context;
@@ -347,6 +349,8 @@ public void Reset()
347349

348350
_remainingRequestHeadersBytesAllowed = ServerOptions.Limits.MaxRequestHeadersTotalSize;
349351
_requestHeadersParsed = 0;
352+
353+
_responseBytesWritten = 0;
350354
}
351355

352356
/// <summary>
@@ -513,6 +517,7 @@ public async Task FlushAsync(CancellationToken cancellationToken)
513517
public void Write(ArraySegment<byte> data)
514518
{
515519
ProduceStartAndFireOnStarting().GetAwaiter().GetResult();
520+
_responseBytesWritten += data.Count;
516521

517522
if (_canHaveBody)
518523
{
@@ -531,7 +536,7 @@ public void Write(ArraySegment<byte> data)
531536
}
532537
else
533538
{
534-
HandleNonBodyResponseWrite(data.Count);
539+
HandleNonBodyResponseWrite();
535540
}
536541
}
537542

@@ -542,6 +547,8 @@ public Task WriteAsync(ArraySegment<byte> data, CancellationToken cancellationTo
542547
return WriteAsyncAwaited(data, cancellationToken);
543548
}
544549

550+
_responseBytesWritten += data.Count;
551+
545552
if (_canHaveBody)
546553
{
547554
if (_autoChunk)
@@ -559,14 +566,15 @@ public Task WriteAsync(ArraySegment<byte> data, CancellationToken cancellationTo
559566
}
560567
else
561568
{
562-
HandleNonBodyResponseWrite(data.Count);
569+
HandleNonBodyResponseWrite();
563570
return TaskCache.CompletedTask;
564571
}
565572
}
566573

567574
public async Task WriteAsyncAwaited(ArraySegment<byte> data, CancellationToken cancellationToken)
568575
{
569576
await ProduceStartAndFireOnStarting();
577+
_responseBytesWritten += data.Count;
570578

571579
if (_canHaveBody)
572580
{
@@ -585,7 +593,7 @@ public async Task WriteAsyncAwaited(ArraySegment<byte> data, CancellationToken c
585593
}
586594
else
587595
{
588-
HandleNonBodyResponseWrite(data.Count);
596+
HandleNonBodyResponseWrite();
589597
return;
590598
}
591599
}
@@ -740,6 +748,11 @@ private Task WriteSuffix()
740748
ConnectionControl.End(ProduceEndType.ConnectionKeepAlive);
741749
}
742750

751+
if (HttpMethods.IsHead(Method) && _responseBytesWritten > 0)
752+
{
753+
Log.ConnectionHeadResponseBodyWrite(ConnectionId, _responseBytesWritten);
754+
}
755+
743756
return TaskCache.CompletedTask;
744757
}
745758

@@ -1324,14 +1337,10 @@ private void SetErrorResponseHeaders(int statusCode)
13241337
}
13251338
}
13261339

1327-
public void HandleNonBodyResponseWrite(int count)
1340+
public void HandleNonBodyResponseWrite()
13281341
{
1329-
if (Method == "HEAD")
1330-
{
1331-
// Don't write to body for HEAD requests.
1332-
Log.ConnectionHeadResponseBodyWrite(ConnectionId, count);
1333-
}
1334-
else
1342+
// Writes to HEAD response are ignored and logged at the end of the request
1343+
if (Method != "HEAD")
13351344
{
13361345
// Throw Exception for 204, 205, 304 responses.
13371346
throw new InvalidOperationException($"Write to non-body {StatusCode} response.");

test/Microsoft.AspNetCore.Server.KestrelTests/EngineTests.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,35 @@ await connection.ReceiveEnd(
620620
}
621621
}
622622

623+
[Theory]
624+
[MemberData(nameof(ConnectionFilterData))]
625+
public async Task WriteOnHeadResponseLoggedOnlyOnce(TestServiceContext testContext)
626+
{
627+
using (var server = new TestServer(async httpContext =>
628+
{
629+
await httpContext.Response.WriteAsync("hello, ");
630+
await httpContext.Response.WriteAsync("world");
631+
await httpContext.Response.WriteAsync("!");
632+
}, testContext))
633+
{
634+
using (var connection = server.CreateConnection())
635+
{
636+
await connection.SendEnd(
637+
"HEAD / HTTP/1.1",
638+
"",
639+
"");
640+
await connection.ReceiveEnd(
641+
"HTTP/1.1 200 OK",
642+
$"Date: {testContext.DateHeaderValue}",
643+
"",
644+
"");
645+
}
646+
647+
Assert.Equal(1, ((TestKestrelTrace)testContext.Log).HeadResponseWrites);
648+
Assert.Equal(13, ((TestKestrelTrace)testContext.Log).HeadResponseWriteByteCount);
649+
}
650+
}
651+
623652
[Theory]
624653
[MemberData(nameof(ConnectionFilterData))]
625654
public async Task ThrowingResultsIn500Response(TestServiceContext testContext)

test/shared/TestKestrelTrace.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ public TestKestrelTrace(ILogger testLogger) : base(testLogger)
1313
{
1414
}
1515

16+
public int HeadResponseWrites { get; set; }
17+
18+
public int HeadResponseWriteByteCount { get; set; }
19+
1620
public override void ConnectionRead(string connectionId, int count)
1721
{
1822
//_logger.LogDebug(1, @"Connection id ""{ConnectionId}"" recv {count} bytes.", connectionId, count);
@@ -27,5 +31,11 @@ public override void ConnectionWriteCallback(string connectionId, int status)
2731
{
2832
//_logger.LogDebug(1, @"Connection id ""{ConnectionId}"" send finished with status {status}.", connectionId, status);
2933
}
34+
35+
public override void ConnectionHeadResponseBodyWrite(string connectionId, int count)
36+
{
37+
HeadResponseWrites++;
38+
HeadResponseWriteByteCount = count;
39+
}
3040
}
3141
}

0 commit comments

Comments
 (0)