@@ -58,6 +58,7 @@ public abstract partial class Frame : ConnectionContext, IFrameControl
58
58
59
59
protected RequestProcessingStatus _requestProcessingStatus ;
60
60
protected bool _keepAlive ;
61
+ private bool _canHaveBody ;
61
62
private bool _autoChunk ;
62
63
protected Exception _applicationException ;
63
64
@@ -465,6 +466,9 @@ public void Write(ArraySegment<byte> data)
465
466
{
466
467
ProduceStartAndFireOnStarting ( ) . GetAwaiter ( ) . GetResult ( ) ;
467
468
469
+ // Don't write to body for HEAD requests or 101, 204, 205, 304 responses.
470
+ if ( ! _canHaveBody ) return ;
471
+
468
472
if ( _autoChunk )
469
473
{
470
474
if ( data . Count == 0 )
@@ -486,6 +490,9 @@ public Task WriteAsync(ArraySegment<byte> data, CancellationToken cancellationTo
486
490
return WriteAsyncAwaited ( data , cancellationToken ) ;
487
491
}
488
492
493
+ // Don't write to body for HEAD requests or 101, 204, 205, 304 responses.
494
+ if ( ! _canHaveBody ) return TaskUtilities . CompletedTask ;
495
+
489
496
if ( _autoChunk )
490
497
{
491
498
if ( data . Count == 0 )
@@ -504,6 +511,9 @@ public async Task WriteAsyncAwaited(ArraySegment<byte> data, CancellationToken c
504
511
{
505
512
await ProduceStartAndFireOnStarting ( ) ;
506
513
514
+ // Don't write to body for HEAD requests or 101, 204, 205, 304 responses.
515
+ if ( ! _canHaveBody ) return ;
516
+
507
517
if ( _autoChunk )
508
518
{
509
519
if ( data . Count == 0 )
@@ -710,10 +720,12 @@ private void CreateResponseHeader(
710
720
bool appCompleted )
711
721
{
712
722
var responseHeaders = FrameResponseHeaders ;
713
- responseHeaders . SetReadOnly ( ) ;
714
723
715
724
var hasConnection = responseHeaders . HasConnection ;
716
725
726
+ // Set whether response can have body
727
+ _canHaveBody = StatusCanHaveBody ( StatusCode ) && Method != "HEAD" ;
728
+
717
729
var end = SocketOutput . ProducingStart ( ) ;
718
730
if ( _keepAlive && hasConnection )
719
731
{
@@ -727,39 +739,49 @@ private void CreateResponseHeader(
727
739
}
728
740
}
729
741
730
- if ( _keepAlive && ! responseHeaders . HasTransferEncoding && ! responseHeaders . HasContentLength )
742
+ if ( _canHaveBody )
731
743
{
732
- if ( appCompleted )
744
+ if ( _keepAlive && ! responseHeaders . HasTransferEncoding && ! responseHeaders . HasContentLength )
733
745
{
734
- // Don't set the Content-Length or Transfer-Encoding headers
735
- // automatically for HEAD requests or 101, 204, 205, 304 responses.
736
- if ( Method != "HEAD" && StatusCanHaveBody ( StatusCode ) )
746
+ if ( appCompleted )
737
747
{
738
748
// Since the app has completed and we are only now generating
739
749
// the headers we can safely set the Content-Length to 0.
740
750
responseHeaders . SetRawContentLength ( "0" , _bytesContentLengthZero ) ;
741
751
}
742
- }
743
- else
744
- {
745
- // Note for future reference: never change this to set _autoChunk to true on HTTP/1.0
746
- // connections, even if we were to infer the client supports it because an HTTP/1.0 request
747
- // was received that used chunked encoding. Sending a chunked response to an HTTP/1.0
748
- // client would break compliance with RFC 7230 (section 3.3.1):
749
- //
750
- // A server MUST NOT send a response containing Transfer-Encoding unless the corresponding
751
- // request indicates HTTP/1.1 (or later).
752
- if ( _httpVersion == HttpVersionType . Http11 )
753
- {
754
- _autoChunk = true ;
755
- responseHeaders . SetRawTransferEncoding ( "chunked" , _bytesTransferEncodingChunked ) ;
756
- }
757
752
else
758
753
{
759
- _keepAlive = false ;
754
+ // Note for future reference: never change this to set _autoChunk to true on HTTP/1.0
755
+ // connections, even if we were to infer the client supports it because an HTTP/1.0 request
756
+ // was received that used chunked encoding. Sending a chunked response to an HTTP/1.0
757
+ // client would break compliance with RFC 7230 (section 3.3.1):
758
+ //
759
+ // A server MUST NOT send a response containing Transfer-Encoding unless the corresponding
760
+ // request indicates HTTP/1.1 (or later).
761
+ if ( _httpVersion == HttpVersionType . Http11 )
762
+ {
763
+ _autoChunk = true ;
764
+ responseHeaders . SetRawTransferEncoding ( "chunked" , _bytesTransferEncodingChunked ) ;
765
+ }
766
+ else
767
+ {
768
+ _keepAlive = false ;
769
+ }
760
770
}
761
771
}
762
772
}
773
+ else
774
+ {
775
+ // Don't set the Content-Length or Transfer-Encoding headers
776
+ // automatically for HEAD requests or 101, 204, 205, 304 responses.
777
+ if ( responseHeaders . HasTransferEncoding )
778
+ {
779
+ // Remove Transfer-Encoding encoding header if it exists
780
+ responseHeaders . Remove ( "Transfer-Encoding" ) ;
781
+ }
782
+ }
783
+
784
+ responseHeaders . SetReadOnly ( ) ;
763
785
764
786
if ( ! _keepAlive && ! hasConnection && _httpVersion != HttpVersionType . Http10 )
765
787
{
0 commit comments