@@ -40,7 +40,6 @@ internal class Http1OutputProducer : IHttpOutputProducer, IDisposable
4040 private bool _aborted ;
4141 private long _unflushedBytes ;
4242 private int _currentMemoryPrefixBytes ;
43- private bool _canWriteBody = true ;
4443
4544 private readonly ConcurrentPipeWriter _pipeWriter ;
4645 private IMemoryOwner < byte > ? _fakeMemoryOwner ;
@@ -52,7 +51,7 @@ internal class Http1OutputProducer : IHttpOutputProducer, IDisposable
5251 // Once write or flush is called, we modify the _currentChunkMemory to prepend the size of data written
5352 // and append the end terminator.
5453
55- private bool _autoChunk ;
54+ private ResponseBodyMode _responseBodyMode ;
5655
5756 private bool _writeStreamSuffixCalled ;
5857
@@ -122,7 +121,7 @@ public ValueTask<FlushResult> WriteStreamSuffixAsync()
122121 {
123122 if ( ! _writeStreamSuffixCalled )
124123 {
125- if ( _autoChunk && _canWriteBody )
124+ if ( _responseBodyMode == ResponseBodyMode . Chunked )
126125 {
127126 var writer = new BufferWriter < PipeWriter > ( _pipeWriter ) ;
128127 result = WriteAsyncInternal ( ref writer , EndChunkedResponseBytes ) ;
@@ -148,7 +147,7 @@ public ValueTask<FlushResult> FlushAsync(CancellationToken cancellationToken = d
148147 return new ValueTask < FlushResult > ( new FlushResult ( false , true ) ) ;
149148 }
150149
151- if ( _autoChunk )
150+ if ( _responseBodyMode == ResponseBodyMode . Chunked )
152151 {
153152 if ( _advancedBytesForChunk > 0 )
154153 {
@@ -174,7 +173,7 @@ static ValueTask<FlushResult> FlushAsyncChunked(Http1OutputProducer producer, Ca
174173 // Local function so in the common-path the stack space for BufferWriter isn't reserved and cleared when it isn't used.
175174
176175 Debug . Assert ( ! producer . _pipeWriterCompleted ) ;
177- Debug . Assert ( producer . _autoChunk && producer . _advancedBytesForChunk > 0 ) ;
176+ Debug . Assert ( producer . _responseBodyMode == ResponseBodyMode . Chunked && producer . _advancedBytesForChunk > 0 ) ;
178177
179178 var writer = new BufferWriter < PipeWriter > ( producer . _pipeWriter ) ;
180179 producer . WriteCurrentChunkMemoryToPipeWriter ( ref writer ) ;
@@ -204,7 +203,7 @@ public Memory<byte> GetMemory(int sizeHint = 0)
204203 {
205204 return LeasedMemory ( sizeHint ) ;
206205 }
207- else if ( _autoChunk )
206+ else if ( _responseBodyMode == ResponseBodyMode . Chunked )
208207 {
209208 return GetChunkedMemory ( sizeHint ) ;
210209 }
@@ -229,7 +228,7 @@ public Span<byte> GetSpan(int sizeHint = 0)
229228 {
230229 return LeasedMemory ( sizeHint ) . Span ;
231230 }
232- else if ( _autoChunk )
231+ else if ( _responseBodyMode == ResponseBodyMode . Chunked )
233232 {
234233 return GetChunkedMemory ( sizeHint ) . Span ;
235234 }
@@ -263,7 +262,7 @@ public void Advance(int bytes)
263262 _position += bytes ;
264263 }
265264 }
266- else if ( _autoChunk )
265+ else if ( _responseBodyMode == ResponseBodyMode . Chunked )
267266 {
268267 if ( _advancedBytesForChunk > _currentChunkMemory . Length - _currentMemoryPrefixBytes - EndChunkLength - bytes )
269268 {
@@ -334,7 +333,7 @@ private void CommitChunkInternal(ref BufferWriter<PipeWriter> writer, ReadOnlySp
334333 writer . Commit ( ) ;
335334 }
336335
337- public void WriteResponseHeaders ( int statusCode , string ? reasonPhrase , HttpResponseHeaders responseHeaders , bool autoChunk , bool appComplete )
336+ public void WriteResponseHeaders ( int statusCode , string ? reasonPhrase , HttpResponseHeaders responseHeaders , ResponseBodyMode responseBodyMode , bool appComplete )
338337 {
339338 lock ( _contextLock )
340339 {
@@ -347,11 +346,11 @@ public void WriteResponseHeaders(int statusCode, string? reasonPhrase, HttpRespo
347346
348347 var buffer = _pipeWriter ;
349348 var writer = new BufferWriter < PipeWriter > ( buffer ) ;
350- WriteResponseHeadersInternal ( ref writer , statusCode , reasonPhrase , responseHeaders , autoChunk ) ;
349+ WriteResponseHeadersInternal ( ref writer , statusCode , reasonPhrase , responseHeaders , responseBodyMode ) ;
351350 }
352351 }
353352
354- private void WriteResponseHeadersInternal ( ref BufferWriter < PipeWriter > writer , int statusCode , string ? reasonPhrase , HttpResponseHeaders responseHeaders , bool autoChunk )
353+ private void WriteResponseHeadersInternal ( ref BufferWriter < PipeWriter > writer , int statusCode , string ? reasonPhrase , HttpResponseHeaders responseHeaders , ResponseBodyMode responseBodyMode )
355354 {
356355 writer . Write ( HttpVersion11Bytes ) ;
357356 var statusBytes = ReasonPhrases . ToStatusBytes ( statusCode , reasonPhrase ) ;
@@ -361,7 +360,7 @@ private void WriteResponseHeadersInternal(ref BufferWriter<PipeWriter> writer, i
361360
362361 writer . Commit ( ) ;
363362
364- _autoChunk = autoChunk ;
363+ _responseBodyMode = responseBodyMode ;
365364 WriteDataWrittenBeforeHeaders ( ref writer ) ;
366365 _unflushedBytes += writer . BytesCommitted ;
367366
@@ -374,17 +373,14 @@ private void WriteDataWrittenBeforeHeaders(ref BufferWriter<PipeWriter> writer)
374373 {
375374 foreach ( var segment in _completedSegments )
376375 {
377- if ( _canWriteBody )
376+ if ( _responseBodyMode == ResponseBodyMode . Chunked )
378377 {
379- if ( _autoChunk )
380- {
381- CommitChunkInternal ( ref writer , segment . Span ) ;
382- }
383- else
384- {
385- writer . Write ( segment . Span ) ;
386- writer . Commit ( ) ;
387- }
378+ CommitChunkInternal ( ref writer , segment . Span ) ;
379+ }
380+ else if ( _responseBodyMode == ResponseBodyMode . ContentLength )
381+ {
382+ writer . Write ( segment . Span ) ;
383+ writer . Commit ( ) ;
388384 }
389385 segment . Return ( ) ;
390386 }
@@ -395,15 +391,15 @@ private void WriteDataWrittenBeforeHeaders(ref BufferWriter<PipeWriter> writer)
395391
396392 if ( ! _currentSegment . IsEmpty )
397393 {
398- if ( _canWriteBody )
394+ if ( _responseBodyMode != ResponseBodyMode . Disabled )
399395 {
400396 var segment = _currentSegment . Slice ( 0 , _position ) ;
401397
402- if ( _autoChunk )
398+ if ( _responseBodyMode == ResponseBodyMode . Chunked )
403399 {
404400 CommitChunkInternal ( ref writer , segment . Span ) ;
405401 }
406- else
402+ else if ( _responseBodyMode == ResponseBodyMode . ContentLength )
407403 {
408404 writer . Write ( segment . Span ) ;
409405 writer . Commit ( ) ;
@@ -498,7 +494,7 @@ public ValueTask<FlushResult> Write100ContinueAsync()
498494 return WriteAsync ( ContinueBytes ) ;
499495 }
500496
501- public ValueTask < FlushResult > FirstWriteAsync ( int statusCode , string ? reasonPhrase , HttpResponseHeaders responseHeaders , bool autoChunk , ReadOnlySpan < byte > buffer , CancellationToken cancellationToken )
497+ public ValueTask < FlushResult > FirstWriteAsync ( int statusCode , string ? reasonPhrase , HttpResponseHeaders responseHeaders , ResponseBodyMode responseBodyMode , ReadOnlySpan < byte > buffer , CancellationToken cancellationToken )
502498 {
503499 lock ( _contextLock )
504500 {
@@ -512,13 +508,13 @@ public ValueTask<FlushResult> FirstWriteAsync(int statusCode, string? reasonPhra
512508 // Uses same BufferWriter to write response headers and response
513509 var writer = new BufferWriter < PipeWriter > ( _pipeWriter ) ;
514510
515- WriteResponseHeadersInternal ( ref writer , statusCode , reasonPhrase , responseHeaders , autoChunk ) ;
511+ WriteResponseHeadersInternal ( ref writer , statusCode , reasonPhrase , responseHeaders , responseBodyMode ) ;
516512
517513 return WriteAsyncInternal ( ref writer , buffer , cancellationToken ) ;
518514 }
519515 }
520516
521- public ValueTask < FlushResult > FirstWriteChunkedAsync ( int statusCode , string ? reasonPhrase , HttpResponseHeaders responseHeaders , bool autoChunk , ReadOnlySpan < byte > buffer , CancellationToken cancellationToken )
517+ public ValueTask < FlushResult > FirstWriteChunkedAsync ( int statusCode , string ? reasonPhrase , HttpResponseHeaders responseHeaders , ResponseBodyMode responseBodyMode , ReadOnlySpan < byte > buffer , CancellationToken cancellationToken )
522518 {
523519 lock ( _contextLock )
524520 {
@@ -532,7 +528,7 @@ public ValueTask<FlushResult> FirstWriteChunkedAsync(int statusCode, string? rea
532528 // Uses same BufferWriter to write response headers and chunk
533529 var writer = new BufferWriter < PipeWriter > ( _pipeWriter ) ;
534530
535- WriteResponseHeadersInternal ( ref writer , statusCode , reasonPhrase , responseHeaders , autoChunk ) ;
531+ WriteResponseHeadersInternal ( ref writer , statusCode , reasonPhrase , responseHeaders , responseBodyMode ) ;
536532
537533 CommitChunkInternal ( ref writer , buffer ) ;
538534
@@ -542,22 +538,16 @@ public ValueTask<FlushResult> FirstWriteChunkedAsync(int statusCode, string? rea
542538 }
543539 }
544540
545- public void SetCanWriteBody ( bool canWriteBody )
546- {
547- _canWriteBody = canWriteBody ;
548- }
549-
550541 public void Reset ( )
551542 {
552543 Debug . Assert ( _currentSegmentOwner == null ) ;
553544 Debug . Assert ( _completedSegments == null || _completedSegments . Count == 0 ) ;
554545 // Cleared in sequential address ascending order
555546 _currentMemoryPrefixBytes = 0 ;
556- _autoChunk = false ;
547+ _responseBodyMode = ResponseBodyMode . ContentLength ;
557548 _writeStreamSuffixCalled = false ;
558549 _currentChunkMemoryUpdated = false ;
559550 _startCalled = false ;
560- _canWriteBody = true ;
561551 }
562552
563553 private ValueTask < FlushResult > WriteAsync (
@@ -583,7 +573,7 @@ private ValueTask<FlushResult> WriteAsyncInternal(
583573 ReadOnlySpan < byte > buffer ,
584574 CancellationToken cancellationToken = default )
585575 {
586- if ( _autoChunk )
576+ if ( _responseBodyMode == ResponseBodyMode . Chunked )
587577 {
588578 if ( _advancedBytesForChunk > 0 )
589579 {
0 commit comments