@@ -364,7 +364,7 @@ public async Task ProcessRequestAsync<TContext>(IHttpApplication<TContext> appli
364364 Log . Http3FrameReceived ( ConnectionId , _streamIdFeature . StreamId , _incomingFrame ) ;
365365
366366 consumed = examined = framePayload . End ;
367- await ProcessHttp3Stream ( application , framePayload ) ;
367+ await ProcessHttp3Stream ( application , framePayload , result . IsCompleted && readableBuffer . IsEmpty ) ;
368368 }
369369 }
370370
@@ -448,14 +448,14 @@ private ValueTask OnEndStreamReceived()
448448 return RequestBodyPipe . Writer . CompleteAsync ( ) ;
449449 }
450450
451- private Task ProcessHttp3Stream < TContext > ( IHttpApplication < TContext > application , in ReadOnlySequence < byte > payload ) where TContext : notnull
451+ private Task ProcessHttp3Stream < TContext > ( IHttpApplication < TContext > application , in ReadOnlySequence < byte > payload , bool isCompleted ) where TContext : notnull
452452 {
453453 switch ( _incomingFrame . Type )
454454 {
455455 case Http3FrameType . Data :
456456 return ProcessDataFrameAsync ( payload ) ;
457457 case Http3FrameType . Headers :
458- return ProcessHeadersFrameAsync ( application , payload ) ;
458+ return ProcessHeadersFrameAsync ( application , payload , isCompleted ) ;
459459 case Http3FrameType . Settings :
460460 case Http3FrameType . CancelPush :
461461 case Http3FrameType . GoAway :
@@ -478,7 +478,7 @@ private Task ProcessUnknownFrameAsync()
478478 return Task . CompletedTask ;
479479 }
480480
481- private Task ProcessHeadersFrameAsync < TContext > ( IHttpApplication < TContext > application , ReadOnlySequence < byte > payload ) where TContext : notnull
481+ private async Task ProcessHeadersFrameAsync < TContext > ( IHttpApplication < TContext > application , ReadOnlySequence < byte > payload , bool isCompleted ) where TContext : notnull
482482 {
483483 // HEADERS frame after trailing headers is invalid.
484484 // https://quicwg.org/base-drafts/draft-ietf-quic-http.html#section-4.1
@@ -506,19 +506,24 @@ private Task ProcessHeadersFrameAsync<TContext>(IHttpApplication<TContext> appli
506506 case RequestHeaderParsingState . Trailers :
507507 // trailers
508508 // TODO figure out if there is anything else to do here.
509- return Task . CompletedTask ;
509+ return ;
510510 default :
511511 Debug . Fail ( "Unexpected header parsing state." ) ;
512512 break ;
513513 }
514514
515515 InputRemaining = HttpRequestHeaders . ContentLength ;
516516
517+ // If the stream is complete after receiving the headers then run OnEndStreamReceived.
518+ // If there is a bad content length then this will throw before the request delegate is called.
519+ if ( isCompleted )
520+ {
521+ await OnEndStreamReceived ( ) ;
522+ }
523+
517524 _appCompleted = new TaskCompletionSource ( ) ;
518525
519526 ThreadPool . UnsafeQueueUserWorkItem ( this , preferLocal : false ) ;
520-
521- return Task . CompletedTask ;
522527 }
523528
524529 private Task ProcessDataFrameAsync ( in ReadOnlySequence < byte > payload )
0 commit comments