@@ -272,20 +272,20 @@ public async Task RequestProcessingAsync()
272
272
273
273
HttpContextFactory . Dispose ( httpContext ) ;
274
274
275
- await ProduceEnd ( ) ;
276
-
277
- var block = Memory2 . Lease ( ) ;
275
+ var memoryBlock = Memory2 . Lease ( ) ;
278
276
try
279
277
{
280
- var segment = block . Data ;
278
+ await ProduceEnd ( memoryBlock ) ;
279
+
280
+ var segment = memoryBlock . Data ;
281
281
while ( await RequestBody . ReadAsync ( segment . Array , segment . Offset , segment . Count ) != 0 )
282
282
{
283
283
// Finish reading the request body in case the app did not.
284
284
}
285
285
}
286
286
finally
287
287
{
288
- Memory2 . Return ( block ) ;
288
+ Memory2 . Return ( memoryBlock ) ;
289
289
}
290
290
}
291
291
@@ -393,19 +393,43 @@ private async Task FireOnCompleted()
393
393
394
394
public void Flush ( )
395
395
{
396
- ProduceStartAndFireOnStarting ( immediate : false ) . GetAwaiter ( ) . GetResult ( ) ;
396
+ var memoryBlock = Memory2 . Lease ( ) ;
397
+ try
398
+ {
399
+ ProduceStartAndFireOnStarting ( memoryBlock , immediate : false ) . GetAwaiter ( ) . GetResult ( ) ;
400
+ }
401
+ finally
402
+ {
403
+ Memory2 . Return ( memoryBlock ) ;
404
+ }
397
405
SocketOutput . Write ( _emptyData , immediate : true ) ;
398
406
}
399
407
400
408
public async Task FlushAsync ( CancellationToken cancellationToken )
401
409
{
402
- await ProduceStartAndFireOnStarting ( immediate : false ) ;
410
+ var memoryBlock = Memory2 . Lease ( ) ;
411
+ try
412
+ {
413
+ await ProduceStartAndFireOnStarting ( memoryBlock , immediate : false ) ;
414
+ }
415
+ finally
416
+ {
417
+ Memory2 . Return ( memoryBlock ) ;
418
+ }
403
419
await SocketOutput . WriteAsync ( _emptyData , immediate : true , cancellationToken : cancellationToken ) ;
404
420
}
405
421
406
422
public void Write ( ArraySegment < byte > data )
407
423
{
408
- ProduceStartAndFireOnStarting ( immediate : false ) . GetAwaiter ( ) . GetResult ( ) ;
424
+ var memoryBlock = Memory2 . Lease ( ) ;
425
+ try
426
+ {
427
+ ProduceStartAndFireOnStarting ( memoryBlock , immediate : false ) . GetAwaiter ( ) . GetResult ( ) ;
428
+ }
429
+ finally
430
+ {
431
+ Memory2 . Return ( memoryBlock ) ;
432
+ }
409
433
410
434
if ( _autoChunk )
411
435
{
@@ -423,7 +447,15 @@ public void Write(ArraySegment<byte> data)
423
447
424
448
public async Task WriteAsync ( ArraySegment < byte > data , CancellationToken cancellationToken )
425
449
{
426
- await ProduceStartAndFireOnStarting ( immediate : false ) ;
450
+ var memoryBlock = Memory2 . Lease ( ) ;
451
+ try
452
+ {
453
+ await ProduceStartAndFireOnStarting ( memoryBlock , immediate : false ) ;
454
+ }
455
+ finally
456
+ {
457
+ Memory2 . Return ( memoryBlock ) ;
458
+ }
427
459
428
460
if ( _autoChunk )
429
461
{
@@ -506,7 +538,7 @@ public void ProduceContinue()
506
538
}
507
539
}
508
540
509
- public async Task ProduceStartAndFireOnStarting ( bool immediate = true )
541
+ public async Task ProduceStartAndFireOnStarting ( MemoryPoolBlock2 memoryBlock , bool immediate = true )
510
542
{
511
543
if ( _responseStarted ) return ;
512
544
@@ -519,20 +551,23 @@ public async Task ProduceStartAndFireOnStarting(bool immediate = true)
519
551
_applicationException ) ;
520
552
}
521
553
522
- await ProduceStart ( immediate , appCompleted : false ) ;
554
+ await ProduceStart ( memoryBlock , immediate , appCompleted : false ) ;
523
555
}
524
556
525
- private Task ProduceStart ( bool immediate , bool appCompleted )
557
+ private Task ProduceStart (
558
+ MemoryPoolBlock2 memoryBlock ,
559
+ bool immediate ,
560
+ bool appCompleted )
526
561
{
527
562
if ( _responseStarted ) return TaskUtilities . CompletedTask ;
528
563
_responseStarted = true ;
529
564
530
565
var statusBytes = ReasonPhrases . ToStatusBytes ( StatusCode , ReasonPhrase ) ;
531
566
532
- return CreateResponseHeader ( statusBytes , appCompleted , immediate ) ;
567
+ return CreateResponseHeader ( statusBytes , memoryBlock , appCompleted , immediate ) ;
533
568
}
534
569
535
- private async Task ProduceEnd ( )
570
+ private async Task ProduceEnd ( MemoryPoolBlock2 memoryBlock )
536
571
{
537
572
if ( _applicationException != null )
538
573
{
@@ -552,7 +587,7 @@ private async Task ProduceEnd()
552
587
}
553
588
}
554
589
555
- await ProduceStart ( immediate : true , appCompleted : true ) ;
590
+ await ProduceStart ( memoryBlock , immediate : true , appCompleted : true ) ;
556
591
557
592
// _autoChunk should be checked after we are sure ProduceStart() has been called
558
593
// since ProduceStart() may set _autoChunk to true.
@@ -620,95 +655,88 @@ private static void OutputAsciiBlock(byte[] data, MemoryPoolBlock2 memoryBlock,
620
655
621
656
private Task CreateResponseHeader (
622
657
byte [ ] statusBytes ,
658
+ MemoryPoolBlock2 memoryBlock ,
623
659
bool appCompleted ,
624
660
bool immediate )
625
661
{
626
- var memoryBlock = Memory2 . Lease ( ) ;
627
- try
628
- {
629
- var blockRemaining = memoryBlock . Data . Count ;
662
+ var blockRemaining = memoryBlock . Data . Count ;
630
663
631
- OutputAsciiBlock ( _httpVersion == HttpVersionType . Http1_1 ? _bytesHttpVersion1_1 : _bytesHttpVersion1_0 , memoryBlock , SocketOutput ) ;
664
+ OutputAsciiBlock ( _httpVersion == HttpVersionType . Http1_1 ? _bytesHttpVersion1_1 : _bytesHttpVersion1_0 , memoryBlock , SocketOutput ) ;
632
665
633
- OutputAsciiBlock ( statusBytes , memoryBlock , SocketOutput ) ;
666
+ OutputAsciiBlock ( statusBytes , memoryBlock , SocketOutput ) ;
667
+
668
+ if ( _responseHeaders . HasDefaultDate )
669
+ {
670
+ OutputAsciiBlock ( _bytesDate , memoryBlock , SocketOutput ) ;
671
+ OutputAsciiBlock ( DateHeaderValueManager . GetDateHeaderValueBytes ( ) , memoryBlock , SocketOutput ) ;
672
+ OutputAsciiBlock ( _bytesEndLine , memoryBlock , SocketOutput ) ;
673
+ }
634
674
635
- if ( _responseHeaders . HasDefaultDate )
675
+ foreach ( var header in _responseHeaders . AsOutputEnumerable ( ) )
676
+ {
677
+ foreach ( var value in header . Value )
636
678
{
637
- OutputAsciiBlock ( _bytesDate , memoryBlock , SocketOutput ) ;
638
- OutputAsciiBlock ( DateHeaderValueManager . GetDateHeaderValueBytes ( ) , memoryBlock , SocketOutput ) ;
679
+ OutputAsciiBlock ( header . Key , memoryBlock , SocketOutput ) ;
680
+ OutputAsciiBlock ( value , memoryBlock , SocketOutput ) ;
639
681
OutputAsciiBlock ( _bytesEndLine , memoryBlock , SocketOutput ) ;
640
- }
641
682
642
- foreach ( var header in _responseHeaders . AsOutputEnumerable ( ) )
643
- {
644
- foreach ( var value in header . Value )
683
+ if ( _responseHeaders . HasConnection && value . IndexOf ( "close" , StringComparison . OrdinalIgnoreCase ) != - 1 )
645
684
{
646
- OutputAsciiBlock ( header . Key , memoryBlock , SocketOutput ) ;
647
- OutputAsciiBlock ( value , memoryBlock , SocketOutput ) ;
648
- OutputAsciiBlock ( _bytesEndLine , memoryBlock , SocketOutput ) ;
649
-
650
- if ( _responseHeaders . HasConnection && value . IndexOf ( "close" , StringComparison . OrdinalIgnoreCase ) != - 1 )
651
- {
652
- _keepAlive = false ;
653
- }
685
+ _keepAlive = false ;
654
686
}
655
687
}
688
+ }
689
+
690
+ if ( _responseHeaders . HasDefaultServer )
691
+ {
692
+ OutputAsciiBlock ( _bytesServer , memoryBlock , SocketOutput ) ;
693
+ }
656
694
657
- if ( _responseHeaders . HasDefaultServer )
695
+ if ( _keepAlive && ! _responseHeaders . HasTransferEncoding && ! _responseHeaders . HasContentLength )
696
+ {
697
+ if ( appCompleted )
658
698
{
659
- OutputAsciiBlock ( _bytesServer , memoryBlock , SocketOutput ) ;
699
+ // Don't set the Content-Length or Transfer-Encoding headers
700
+ // automatically for HEAD requests or 101, 204, 205, 304 responses.
701
+ if ( Method != "HEAD" && StatusCanHaveBody ( StatusCode ) )
702
+ {
703
+ // Since the app has completed and we are only now generating
704
+ // the headers we can safely set the Content-Length to 0.
705
+ OutputAsciiBlock ( _bytesContentLengthZero , memoryBlock , SocketOutput ) ;
706
+ }
660
707
}
661
-
662
- if ( _keepAlive && ! _responseHeaders . HasTransferEncoding && ! _responseHeaders . HasContentLength )
708
+ else
663
709
{
664
- if ( appCompleted )
710
+ if ( _httpVersion == HttpVersionType . Http1_1 )
665
711
{
666
- // Don't set the Content-Length or Transfer-Encoding headers
667
- // automatically for HEAD requests or 101, 204, 205, 304 responses.
668
- if ( Method != "HEAD" && StatusCanHaveBody ( StatusCode ) )
669
- {
670
- // Since the app has completed and we are only now generating
671
- // the headers we can safely set the Content-Length to 0.
672
- OutputAsciiBlock ( _bytesContentLengthZero , memoryBlock , SocketOutput ) ;
673
- }
712
+ _autoChunk = true ;
713
+ OutputAsciiBlock ( _bytesTransferEncodingChunked , memoryBlock , SocketOutput ) ;
674
714
}
675
715
else
676
716
{
677
- if ( _httpVersion == HttpVersionType . Http1_1 )
678
- {
679
- _autoChunk = true ;
680
- OutputAsciiBlock ( _bytesTransferEncodingChunked , memoryBlock , SocketOutput ) ;
681
- }
682
- else
683
- {
684
- _keepAlive = false ;
685
- }
717
+ _keepAlive = false ;
686
718
}
687
719
}
720
+ }
688
721
689
- if ( _keepAlive == false && _responseHeaders . HasConnection == false && _httpVersion == HttpVersionType . Http1_1 )
690
- {
691
- OutputAsciiBlock ( _bytesConnectionClose , memoryBlock , SocketOutput ) ;
692
- }
693
- else if ( _keepAlive && _responseHeaders . HasConnection == false && _httpVersion == HttpVersionType . Http1_0 )
694
- {
695
- OutputAsciiBlock ( _bytesConnectionKeepAlive , memoryBlock , SocketOutput ) ;
696
- }
697
- else
698
- {
699
- OutputAsciiBlock ( _bytesEndLine , memoryBlock , SocketOutput ) ;
700
- }
701
-
702
- return SocketOutput . WriteAsync (
703
- ( memoryBlock . Start == memoryBlock . End ) ?
704
- default ( ArraySegment < byte > ) :
705
- new ArraySegment < byte > ( memoryBlock . Array , memoryBlock . Start , memoryBlock . End - memoryBlock . Start ) ,
706
- immediate ) ;
722
+ if ( _keepAlive == false && _responseHeaders . HasConnection == false && _httpVersion == HttpVersionType . Http1_1 )
723
+ {
724
+ OutputAsciiBlock ( _bytesConnectionClose , memoryBlock , SocketOutput ) ;
707
725
}
708
- finally
726
+ else if ( _keepAlive && _responseHeaders . HasConnection == false && _httpVersion == HttpVersionType . Http1_0 )
709
727
{
710
- Memory2 . Return ( memoryBlock ) ;
728
+ OutputAsciiBlock ( _bytesConnectionKeepAlive , memoryBlock , SocketOutput ) ;
711
729
}
730
+ else
731
+ {
732
+ OutputAsciiBlock ( _bytesEndLine , memoryBlock , SocketOutput ) ;
733
+ }
734
+
735
+ return SocketOutput . WriteAsync (
736
+ ( memoryBlock . Start == memoryBlock . End ) ?
737
+ default ( ArraySegment < byte > ) :
738
+ new ArraySegment < byte > ( memoryBlock . Array , memoryBlock . Start , memoryBlock . End - memoryBlock . Start ) ,
739
+ immediate ) ;
712
740
}
713
741
714
742
private bool TakeStartLine ( SocketInput input )
0 commit comments