@@ -51,7 +51,7 @@ internal class Http1OutputProducer : IHttpOutputProducer, IDisposable
51
51
// Once write or flush is called, we modify the _currentChunkMemory to prepend the size of data written
52
52
// and append the end terminator.
53
53
54
- private bool _autoChunk ;
54
+ private ResponseBodyMode _responseBodyMode ;
55
55
56
56
private bool _writeStreamSuffixCalled ;
57
57
@@ -121,7 +121,7 @@ public ValueTask<FlushResult> WriteStreamSuffixAsync()
121
121
{
122
122
if ( ! _writeStreamSuffixCalled )
123
123
{
124
- if ( _autoChunk )
124
+ if ( _responseBodyMode == ResponseBodyMode . Chunked )
125
125
{
126
126
var writer = new BufferWriter < PipeWriter > ( _pipeWriter ) ;
127
127
result = WriteAsyncInternal ( ref writer , EndChunkedResponseBytes ) ;
@@ -147,7 +147,7 @@ public ValueTask<FlushResult> FlushAsync(CancellationToken cancellationToken = d
147
147
return new ValueTask < FlushResult > ( new FlushResult ( false , true ) ) ;
148
148
}
149
149
150
- if ( _autoChunk )
150
+ if ( _responseBodyMode == ResponseBodyMode . Chunked )
151
151
{
152
152
if ( _advancedBytesForChunk > 0 )
153
153
{
@@ -173,7 +173,7 @@ static ValueTask<FlushResult> FlushAsyncChunked(Http1OutputProducer producer, Ca
173
173
// Local function so in the common-path the stack space for BufferWriter isn't reserved and cleared when it isn't used.
174
174
175
175
Debug . Assert ( ! producer . _pipeWriterCompleted ) ;
176
- Debug . Assert ( producer . _autoChunk && producer . _advancedBytesForChunk > 0 ) ;
176
+ Debug . Assert ( producer . _responseBodyMode == ResponseBodyMode . Chunked && producer . _advancedBytesForChunk > 0 ) ;
177
177
178
178
var writer = new BufferWriter < PipeWriter > ( producer . _pipeWriter ) ;
179
179
producer . WriteCurrentChunkMemoryToPipeWriter ( ref writer ) ;
@@ -203,7 +203,7 @@ public Memory<byte> GetMemory(int sizeHint = 0)
203
203
{
204
204
return LeasedMemory ( sizeHint ) ;
205
205
}
206
- else if ( _autoChunk )
206
+ else if ( _responseBodyMode == ResponseBodyMode . Chunked )
207
207
{
208
208
return GetChunkedMemory ( sizeHint ) ;
209
209
}
@@ -228,7 +228,7 @@ public Span<byte> GetSpan(int sizeHint = 0)
228
228
{
229
229
return LeasedMemory ( sizeHint ) . Span ;
230
230
}
231
- else if ( _autoChunk )
231
+ else if ( _responseBodyMode == ResponseBodyMode . Chunked )
232
232
{
233
233
return GetChunkedMemory ( sizeHint ) . Span ;
234
234
}
@@ -262,7 +262,7 @@ public void Advance(int bytes)
262
262
_position += bytes ;
263
263
}
264
264
}
265
- else if ( _autoChunk )
265
+ else if ( _responseBodyMode == ResponseBodyMode . Chunked )
266
266
{
267
267
if ( _advancedBytesForChunk > _currentChunkMemory . Length - _currentMemoryPrefixBytes - EndChunkLength - bytes )
268
268
{
@@ -333,7 +333,7 @@ private void CommitChunkInternal(ref BufferWriter<PipeWriter> writer, ReadOnlySp
333
333
writer . Commit ( ) ;
334
334
}
335
335
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 )
337
337
{
338
338
lock ( _contextLock )
339
339
{
@@ -346,11 +346,11 @@ public void WriteResponseHeaders(int statusCode, string? reasonPhrase, HttpRespo
346
346
347
347
var buffer = _pipeWriter ;
348
348
var writer = new BufferWriter < PipeWriter > ( buffer ) ;
349
- WriteResponseHeadersInternal ( ref writer , statusCode , reasonPhrase , responseHeaders , autoChunk ) ;
349
+ WriteResponseHeadersInternal ( ref writer , statusCode , reasonPhrase , responseHeaders , responseBodyMode ) ;
350
350
}
351
351
}
352
352
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 )
354
354
{
355
355
writer . Write ( HttpVersion11Bytes ) ;
356
356
var statusBytes = ReasonPhrases . ToStatusBytes ( statusCode , reasonPhrase ) ;
@@ -360,7 +360,8 @@ private void WriteResponseHeadersInternal(ref BufferWriter<PipeWriter> writer, i
360
360
361
361
writer . Commit ( ) ;
362
362
363
- _autoChunk = autoChunk ;
363
+ Debug . Assert ( responseBodyMode != ResponseBodyMode . Uninitialized ) ;
364
+ _responseBodyMode = responseBodyMode ;
364
365
WriteDataWrittenBeforeHeaders ( ref writer ) ;
365
366
_unflushedBytes += writer . BytesCommitted ;
366
367
@@ -373,11 +374,11 @@ private void WriteDataWrittenBeforeHeaders(ref BufferWriter<PipeWriter> writer)
373
374
{
374
375
foreach ( var segment in _completedSegments )
375
376
{
376
- if ( _autoChunk )
377
+ if ( _responseBodyMode == ResponseBodyMode . Chunked )
377
378
{
378
379
CommitChunkInternal ( ref writer , segment . Span ) ;
379
380
}
380
- else
381
+ else if ( _responseBodyMode == ResponseBodyMode . ContentLength )
381
382
{
382
383
writer . Write ( segment . Span ) ;
383
384
writer . Commit ( ) ;
@@ -391,16 +392,19 @@ private void WriteDataWrittenBeforeHeaders(ref BufferWriter<PipeWriter> writer)
391
392
392
393
if ( ! _currentSegment . IsEmpty )
393
394
{
394
- var segment = _currentSegment . Slice ( 0 , _position ) ;
395
-
396
- if ( _autoChunk )
395
+ if ( _responseBodyMode != ResponseBodyMode . Disabled )
397
396
{
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
+ }
404
408
}
405
409
406
410
_position = 0 ;
@@ -491,7 +495,7 @@ public ValueTask<FlushResult> Write100ContinueAsync()
491
495
return WriteAsync ( ContinueBytes ) ;
492
496
}
493
497
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 )
495
499
{
496
500
lock ( _contextLock )
497
501
{
@@ -505,13 +509,13 @@ public ValueTask<FlushResult> FirstWriteAsync(int statusCode, string? reasonPhra
505
509
// Uses same BufferWriter to write response headers and response
506
510
var writer = new BufferWriter < PipeWriter > ( _pipeWriter ) ;
507
511
508
- WriteResponseHeadersInternal ( ref writer , statusCode , reasonPhrase , responseHeaders , autoChunk ) ;
512
+ WriteResponseHeadersInternal ( ref writer , statusCode , reasonPhrase , responseHeaders , responseBodyMode ) ;
509
513
510
514
return WriteAsyncInternal ( ref writer , buffer , cancellationToken ) ;
511
515
}
512
516
}
513
517
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 )
515
519
{
516
520
lock ( _contextLock )
517
521
{
@@ -525,7 +529,7 @@ public ValueTask<FlushResult> FirstWriteChunkedAsync(int statusCode, string? rea
525
529
// Uses same BufferWriter to write response headers and chunk
526
530
var writer = new BufferWriter < PipeWriter > ( _pipeWriter ) ;
527
531
528
- WriteResponseHeadersInternal ( ref writer , statusCode , reasonPhrase , responseHeaders , autoChunk ) ;
532
+ WriteResponseHeadersInternal ( ref writer , statusCode , reasonPhrase , responseHeaders , responseBodyMode ) ;
529
533
530
534
CommitChunkInternal ( ref writer , buffer ) ;
531
535
@@ -541,7 +545,7 @@ public void Reset()
541
545
Debug . Assert ( _completedSegments == null || _completedSegments . Count == 0 ) ;
542
546
// Cleared in sequential address ascending order
543
547
_currentMemoryPrefixBytes = 0 ;
544
- _autoChunk = false ;
548
+ _responseBodyMode = ResponseBodyMode . Uninitialized ;
545
549
_writeStreamSuffixCalled = false ;
546
550
_currentChunkMemoryUpdated = false ;
547
551
_startCalled = false ;
@@ -570,7 +574,7 @@ private ValueTask<FlushResult> WriteAsyncInternal(
570
574
ReadOnlySpan < byte > buffer ,
571
575
CancellationToken cancellationToken = default )
572
576
{
573
- if ( _autoChunk )
577
+ if ( _responseBodyMode == ResponseBodyMode . Chunked )
574
578
{
575
579
if ( _advancedBytesForChunk > 0 )
576
580
{
0 commit comments