@@ -438,7 +438,7 @@ public function handleHeaders(int $streamId, array $pseudo, array $headers, bool
438438 $ stream ->responsePending = false ;
439439 EventLoop::queue (static function () use ($ response , $ stream ): void {
440440 try {
441- $ stream ->requestBodyCompletion ->getFuture ()->await ();
441+ $ stream ->requestHeaderCompletion ->getFuture ()->await ();
442442 $ stream ->preResponseResolution ?->await();
443443 $ stream ->pendingResponse ?->complete($ response );
444444 } catch (\Throwable $ e ) {
@@ -967,22 +967,22 @@ public function request(Request $request, Cancellation $cancellation, Stream $st
967967 $ streamId = $ this ->streamId += 2 ; // Client streams should be odd-numbered, starting at 1.
968968
969969 $ this ->streams [$ streamId ] = $ http2stream = new Http2Stream (
970- $ streamId ,
971- $ request ,
972- $ stream ,
973- $ cancellation ,
974- $ this ->createStreamTransferWatcher ($ streamId , $ request ->getTransferTimeout ()),
975- $ this ->createStreamInactivityWatcher ($ streamId , $ request ->getInactivityTimeout ()),
976- self ::DEFAULT_WINDOW_SIZE ,
977- $ this ->initialWindowSize ,
970+ id: $ streamId ,
971+ request: $ request ,
972+ stream: $ stream ,
973+ cancellation: $ cancellation ,
974+ transferWatcher: $ this ->createStreamTransferWatcher ($ streamId , $ request ->getTransferTimeout ()),
975+ inactivityWatcher: $ this ->createStreamInactivityWatcher ($ streamId , $ request ->getInactivityTimeout ()),
976+ serverWindow: self ::DEFAULT_WINDOW_SIZE ,
977+ clientWindow: $ this ->initialWindowSize ,
978978 );
979979
980+ $ cancellation = $ http2stream ->cancellation ; // Use CompositeCancellation from Http2Stream.
981+
980982 $ cancellationId = $ cancellation ->subscribe (
981983 fn (CancelledException $ exception ) => $ this ->releaseStream ($ streamId , $ exception , false ),
982984 );
983985
984- $ cancellation = $ http2stream ->cancellation ; // Use CompositeCancellation from Http2Stream.
985-
986986 \assert ($ http2stream ->pendingResponse !== null );
987987 $ responseFuture = $ http2stream ->pendingResponse ->getFuture ();
988988
@@ -991,7 +991,7 @@ public function request(Request $request, Cancellation $cancellation, Stream $st
991991 ->finally (static fn () => $ cancellation ->unsubscribe ($ cancellationId ))
992992 ->ignore ();
993993
994- try {
994+ async ( function () use ( $ request , $ stream , $ http2stream , $ cancellation ): void {
995995 events ()->requestHeaderStart ($ request , $ stream );
996996
997997 $ body = $ request ->getBody ()->getContent ();
@@ -1007,64 +1007,64 @@ public function request(Request $request, Cancellation $cancellation, Stream $st
10071007 $ firstChunk = \array_shift ($ split );
10081008 $ lastChunk = \array_pop ($ split );
10091009
1010- $ this ->writeFrame (Http2Parser::HEADERS , Http2Parser:: NO_FLAG , $ streamId , $ firstChunk )->ignore ();
1010+ $ this ->writeFrame (Http2Parser::HEADERS , stream: $ http2stream -> id , data: $ firstChunk )->ignore ();
10111011
10121012 foreach ($ split as $ headerChunk ) {
1013- $ this ->writeFrame (Http2Parser::CONTINUATION , Http2Parser:: NO_FLAG , $ streamId , $ headerChunk )->ignore ();
1013+ $ this ->writeFrame (Http2Parser::CONTINUATION , stream: $ http2stream -> id , data: $ headerChunk )->ignore ();
10141014 }
10151015
1016- $ this ->writeFrame (Http2Parser::CONTINUATION , $ flag , $ streamId , $ lastChunk )->await ();
1016+ $ this ->writeFrame (Http2Parser::CONTINUATION , $ flag , $ http2stream -> id , $ lastChunk )->await ();
10171017 } else {
1018- $ this ->writeFrame (Http2Parser::HEADERS , $ flag , $ streamId , $ headers )->await ();
1018+ $ this ->writeFrame (Http2Parser::HEADERS , $ flag , $ http2stream -> id , $ headers )->await ();
10191019 }
10201020
1021+ $ http2stream ->requestHeaderCompletion ->complete ();
1022+
10211023 events ()->requestHeaderEnd ($ request , $ stream );
10221024
10231025 events ()->requestBodyStart ($ request , $ stream );
10241026
10251027 if ($ chunk === null ) {
10261028 $ http2stream ->requestBodyCompletion ->complete ();
10271029 } else {
1028- $ buffer = $ chunk ;
10291030 $ writeFuture = Future::complete ();
10301031 do {
1031- $ chunk = $ body ->read ($ cancellation );
1032-
1033- if (!isset ($ this ->streams [$ streamId ])) {
1034- // Request stream closed, so this await will throw.
1035- return $ responseFuture ->await ();
1036- }
1037-
10381032 // Wait for prior write to complete if we've buffered too much of the request body.
10391033 if (\strlen ($ http2stream ->requestBodyBuffer ) >= self ::DEFAULT_MAX_FRAME_SIZE ) {
10401034 $ writeFuture ->await ($ cancellation );
10411035 }
10421036
1043- if ($ chunk === null ) {
1044- // Don't move this out of the loop, this needs to be set before calling writeData
1045- $ http2stream ->requestBodyCompletion ->complete ();
1046- }
1047-
1048- $ writeFuture = $ this ->writeData ($ http2stream , $ buffer );
1037+ $ writeFuture = $ this ->writeData ($ http2stream , $ chunk );
10491038 events ()->requestBodyProgress ($ request , $ stream );
1050- $ buffer = $ chunk ;
1051- } while ($ buffer !== null );
1039+
1040+ $ chunk = $ body ->read ($ cancellation );
1041+ } while ($ chunk !== null );
1042+
1043+ $ http2stream ->requestBodyCompletion ->complete ();
10521044
10531045 $ writeFuture ->await ($ cancellation );
1046+ $ this ->writeBufferedData ($ http2stream )->await ($ cancellation );
10541047 }
10551048
10561049 events ()->requestBodyEnd ($ request , $ stream );
1057- } catch (\Throwable $ exception ) {
1050+ })-> catch ( function (\Throwable $ exception ) use ( $ http2stream , $ cancellation , $ cancellationId ): void {
10581051 $ cancellation ->unsubscribe ($ cancellationId );
10591052
1060- $ exception = $ this ->wrapException ($ exception , "Failed to write request (stream {$ streamId }) to socket " );
1053+ $ exception = $ this ->wrapException (
1054+ $ exception ,
1055+ "Failed to write request (stream {$ http2stream ->id }) to socket " ,
1056+ );
1057+
1058+ if (!$ http2stream ->requestHeaderCompletion ->isComplete ()) {
1059+ $ http2stream ->requestHeaderCompletion ->error ($ exception );
1060+ }
10611061
10621062 if (!$ http2stream ->requestBodyCompletion ->isComplete ()) {
10631063 $ http2stream ->requestBodyCompletion ->error ($ exception );
10641064 }
10651065
1066- $ this ->releaseStream ($ streamId , $ exception , false );
1067- }
1066+ $ this ->releaseStream ($ http2stream -> id , $ exception , false );
1067+ });
10681068
10691069 return $ responseFuture ->await ();
10701070 }
@@ -1229,7 +1229,7 @@ private function applySetting(int $setting, int $value): void
12291229
12301230 private function writeBufferedData (Http2Stream $ stream ): Future
12311231 {
1232- if ($ stream ->requestBodyCompletion -> isComplete () && $ stream -> requestBodyBuffer === '' ) {
1232+ if ($ stream ->ended ) {
12331233 return Future::complete ();
12341234 }
12351235
@@ -1261,6 +1261,8 @@ private function writeBufferedData(Http2Stream $stream): Future
12611261 $ stream ->id ,
12621262 $ stream ->requestBodyBuffer
12631263 );
1264+
1265+ $ stream ->ended = true ;
12641266 } else {
12651267 $ future = $ this ->writeFrame (
12661268 Http2Parser::DATA ,
0 commit comments