@@ -51,7 +51,7 @@ internal class Http1OutputProducer : IHttpOutputProducer, IDisposable
5151 // Once write or flush is called, we modify the _currentChunkMemory to prepend the size of data written
5252 // and append the end terminator.
5353
54- private bool _autoChunk ;
54+ private ResponseBodyMode _responseBodyMode ;
5555
5656 private bool _writeStreamSuffixCalled ;
5757
@@ -121,7 +121,7 @@ public ValueTask<FlushResult> WriteStreamSuffixAsync()
121121 {
122122 if ( ! _writeStreamSuffixCalled )
123123 {
124- if ( _autoChunk )
124+ if ( _responseBodyMode == ResponseBodyMode . Chunked )
125125 {
126126 var writer = new BufferWriter < PipeWriter > ( _pipeWriter ) ;
127127 result = WriteAsyncInternal ( ref writer , EndChunkedResponseBytes ) ;
@@ -147,7 +147,7 @@ public ValueTask<FlushResult> FlushAsync(CancellationToken cancellationToken = d
147147 return new ValueTask < FlushResult > ( new FlushResult ( false , true ) ) ;
148148 }
149149
150- if ( _autoChunk )
150+ if ( _responseBodyMode == ResponseBodyMode . Chunked )
151151 {
152152 if ( _advancedBytesForChunk > 0 )
153153 {
@@ -173,7 +173,7 @@ static ValueTask<FlushResult> FlushAsyncChunked(Http1OutputProducer producer, Ca
173173 // Local function so in the common-path the stack space for BufferWriter isn't reserved and cleared when it isn't used.
174174
175175 Debug . Assert ( ! producer . _pipeWriterCompleted ) ;
176- Debug . Assert ( producer . _autoChunk && producer . _advancedBytesForChunk > 0 ) ;
176+ Debug . Assert ( producer . _responseBodyMode == ResponseBodyMode . Chunked && producer . _advancedBytesForChunk > 0 ) ;
177177
178178 var writer = new BufferWriter < PipeWriter > ( producer . _pipeWriter ) ;
179179 producer . WriteCurrentChunkMemoryToPipeWriter ( ref writer ) ;
@@ -203,7 +203,7 @@ public Memory<byte> GetMemory(int sizeHint = 0)
203203 {
204204 return LeasedMemory ( sizeHint ) ;
205205 }
206- else if ( _autoChunk )
206+ else if ( _responseBodyMode == ResponseBodyMode . Chunked )
207207 {
208208 return GetChunkedMemory ( sizeHint ) ;
209209 }
@@ -228,7 +228,7 @@ public Span<byte> GetSpan(int sizeHint = 0)
228228 {
229229 return LeasedMemory ( sizeHint ) . Span ;
230230 }
231- else if ( _autoChunk )
231+ else if ( _responseBodyMode == ResponseBodyMode . Chunked )
232232 {
233233 return GetChunkedMemory ( sizeHint ) . Span ;
234234 }
@@ -262,7 +262,7 @@ public void Advance(int bytes)
262262 _position += bytes ;
263263 }
264264 }
265- else if ( _autoChunk )
265+ else if ( _responseBodyMode == ResponseBodyMode . Chunked )
266266 {
267267 if ( _advancedBytesForChunk > _currentChunkMemory . Length - _currentMemoryPrefixBytes - EndChunkLength - bytes )
268268 {
@@ -333,7 +333,7 @@ private void CommitChunkInternal(ref BufferWriter<PipeWriter> writer, ReadOnlySp
333333 writer . Commit ( ) ;
334334 }
335335
336- 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 )
337337 {
338338 lock ( _contextLock )
339339 {
@@ -346,11 +346,11 @@ public void WriteResponseHeaders(int statusCode, string? reasonPhrase, HttpRespo
346346
347347 var buffer = _pipeWriter ;
348348 var writer = new BufferWriter < PipeWriter > ( buffer ) ;
349- WriteResponseHeadersInternal ( ref writer , statusCode , reasonPhrase , responseHeaders , autoChunk ) ;
349+ WriteResponseHeadersInternal ( ref writer , statusCode , reasonPhrase , responseHeaders , responseBodyMode ) ;
350350 }
351351 }
352352
353- 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 )
354354 {
355355 writer . Write ( HttpVersion11Bytes ) ;
356356 var statusBytes = ReasonPhrases . ToStatusBytes ( statusCode , reasonPhrase ) ;
@@ -360,7 +360,8 @@ private void WriteResponseHeadersInternal(ref BufferWriter<PipeWriter> writer, i
360360
361361 writer . Commit ( ) ;
362362
363- _autoChunk = autoChunk ;
363+ Debug . Assert ( responseBodyMode != ResponseBodyMode . Uninitialized ) ;
364+ _responseBodyMode = responseBodyMode ;
364365 WriteDataWrittenBeforeHeaders ( ref writer ) ;
365366 _unflushedBytes += writer . BytesCommitted ;
366367
@@ -373,11 +374,11 @@ private void WriteDataWrittenBeforeHeaders(ref BufferWriter<PipeWriter> writer)
373374 {
374375 foreach ( var segment in _completedSegments )
375376 {
376- if ( _autoChunk )
377+ if ( _responseBodyMode == ResponseBodyMode . Chunked )
377378 {
378379 CommitChunkInternal ( ref writer , segment . Span ) ;
379380 }
380- else
381+ else if ( _responseBodyMode == ResponseBodyMode . ContentLength )
381382 {
382383 writer . Write ( segment . Span ) ;
383384 writer . Commit ( ) ;
@@ -391,16 +392,19 @@ private void WriteDataWrittenBeforeHeaders(ref BufferWriter<PipeWriter> writer)
391392
392393 if ( ! _currentSegment . IsEmpty )
393394 {
394- var segment = _currentSegment . Slice ( 0 , _position ) ;
395-
396- if ( _autoChunk )
395+ if ( _responseBodyMode != ResponseBodyMode . Disabled )
397396 {
398- CommitChunkInternal ( ref writer , segment . Span ) ;
399- }
400- else
401- {
402- writer . Write ( segment . Span ) ;
403- writer . Commit ( ) ;
397+ var segment = _currentSegment . Slice ( 0 , _position ) ;
398+
399+ if ( _responseBodyMode == ResponseBodyMode . Chunked )
400+ {
401+ CommitChunkInternal ( ref writer , segment . Span ) ;
402+ }
403+ else if ( _responseBodyMode == ResponseBodyMode . ContentLength )
404+ {
405+ writer . Write ( segment . Span ) ;
406+ writer . Commit ( ) ;
407+ }
404408 }
405409
406410 _position = 0 ;
@@ -491,7 +495,7 @@ public ValueTask<FlushResult> Write100ContinueAsync()
491495 return WriteAsync ( ContinueBytes ) ;
492496 }
493497
494- public ValueTask < FlushResult > FirstWriteAsync ( int statusCode , string ? reasonPhrase , HttpResponseHeaders responseHeaders , bool autoChunk , ReadOnlySpan < byte > buffer , CancellationToken cancellationToken )
498+ public ValueTask < FlushResult > FirstWriteAsync ( int statusCode , string ? reasonPhrase , HttpResponseHeaders responseHeaders , ResponseBodyMode responseBodyMode , ReadOnlySpan < byte > buffer , CancellationToken cancellationToken )
495499 {
496500 lock ( _contextLock )
497501 {
@@ -505,13 +509,13 @@ public ValueTask<FlushResult> FirstWriteAsync(int statusCode, string? reasonPhra
505509 // Uses same BufferWriter to write response headers and response
506510 var writer = new BufferWriter < PipeWriter > ( _pipeWriter ) ;
507511
508- WriteResponseHeadersInternal ( ref writer , statusCode , reasonPhrase , responseHeaders , autoChunk ) ;
512+ WriteResponseHeadersInternal ( ref writer , statusCode , reasonPhrase , responseHeaders , responseBodyMode ) ;
509513
510514 return WriteAsyncInternal ( ref writer , buffer , cancellationToken ) ;
511515 }
512516 }
513517
514- public ValueTask < FlushResult > FirstWriteChunkedAsync ( int statusCode , string ? reasonPhrase , HttpResponseHeaders responseHeaders , bool autoChunk , ReadOnlySpan < byte > buffer , CancellationToken cancellationToken )
518+ public ValueTask < FlushResult > FirstWriteChunkedAsync ( int statusCode , string ? reasonPhrase , HttpResponseHeaders responseHeaders , ResponseBodyMode responseBodyMode , ReadOnlySpan < byte > buffer , CancellationToken cancellationToken )
515519 {
516520 lock ( _contextLock )
517521 {
@@ -525,7 +529,7 @@ public ValueTask<FlushResult> FirstWriteChunkedAsync(int statusCode, string? rea
525529 // Uses same BufferWriter to write response headers and chunk
526530 var writer = new BufferWriter < PipeWriter > ( _pipeWriter ) ;
527531
528- WriteResponseHeadersInternal ( ref writer , statusCode , reasonPhrase , responseHeaders , autoChunk ) ;
532+ WriteResponseHeadersInternal ( ref writer , statusCode , reasonPhrase , responseHeaders , responseBodyMode ) ;
529533
530534 CommitChunkInternal ( ref writer , buffer ) ;
531535
@@ -541,7 +545,7 @@ public void Reset()
541545 Debug . Assert ( _completedSegments == null || _completedSegments . Count == 0 ) ;
542546 // Cleared in sequential address ascending order
543547 _currentMemoryPrefixBytes = 0 ;
544- _autoChunk = false ;
548+ _responseBodyMode = ResponseBodyMode . Uninitialized ;
545549 _writeStreamSuffixCalled = false ;
546550 _currentChunkMemoryUpdated = false ;
547551 _startCalled = false ;
@@ -570,7 +574,7 @@ private ValueTask<FlushResult> WriteAsyncInternal(
570574 ReadOnlySpan < byte > buffer ,
571575 CancellationToken cancellationToken = default )
572576 {
573- if ( _autoChunk )
577+ if ( _responseBodyMode == ResponseBodyMode . Chunked )
574578 {
575579 if ( _advancedBytesForChunk > 0 )
576580 {
0 commit comments