Skip to content

Commit f147836

Browse files
authored
Avoid hanging requests in case a request body is closed prematurely (#380)
1 parent c60cde9 commit f147836

2 files changed

Lines changed: 11 additions & 2 deletions

File tree

src/Driver/Http1Driver.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -882,6 +882,8 @@ private function send(?Future $lastWrite, Response $response, ?Request $request
882882

883883
$chunk = "HTTP/$protocol $status $reason\r\n" . Rfc7230::formatHeaders($headers) . "\r\n";
884884

885+
$need = $headers["content-length"] ?? null;
886+
$wrote = 0;
885887
try {
886888
$this->writableStream->write($chunk);
887889

@@ -891,6 +893,7 @@ private function send(?Future $lastWrite, Response $response, ?Request $request
891893
if ($shouldClose) {
892894
$this->writableStream->end();
893895
}
896+
$need = null;
894897

895898
return;
896899
}
@@ -905,6 +908,7 @@ private function send(?Future $lastWrite, Response $response, ?Request $request
905908
if ($chunk === "") {
906909
continue;
907910
}
911+
$wrote += strlen($chunk);
908912

909913
if ($chunked) {
910914
$chunk = \sprintf("%x\r\n%s\r\n", \strlen($chunk), $chunk);
@@ -935,7 +939,7 @@ private function send(?Future $lastWrite, Response $response, ?Request $request
935939
return; // Client will be closed in finally.
936940
} finally {
937941
/** @psalm-suppress TypeDoesNotContainType */
938-
if ($chunk !== null) {
942+
if ($chunk !== null || ($need !== null && $wrote !== (int) $need)) {
939943
$this->client->close();
940944
}
941945
}

src/Driver/Http2Driver.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,9 @@ private function send(int $id, Response $response, Request $request, Cancellatio
286286
{
287287
$chunk = ""; // Required for the finally, not directly overwritten, even if your IDE says otherwise.
288288

289+
$need = $response->getHeader("content-length");
290+
$wrote = 0;
291+
289292
try {
290293
$status = $response->getStatus();
291294

@@ -333,6 +336,7 @@ private function send(int $id, Response $response, Request $request, Cancellatio
333336
if ($request->getMethod() === "HEAD") {
334337
$this->streams[$id]->state |= Http2Stream::LOCAL_CLOSED;
335338
$this->writeData("", $id);
339+
$need = null;
336340
return;
337341
}
338342

@@ -344,6 +348,7 @@ private function send(int $id, Response $response, Request $request, Cancellatio
344348
if (!isset($this->streams[$id])) {
345349
return;
346350
}
351+
$wrote += strlen($chunk);
347352

348353
$this->writeData($chunk, $id);
349354

@@ -390,7 +395,7 @@ private function send(int $id, Response $response, Request $request, Cancellatio
390395
return;
391396
}
392397

393-
if ($chunk !== null) {
398+
if ($chunk !== null || ($need !== null && $wrote !== (int) $need)) {
394399
$error ??= Http2Parser::INTERNAL_ERROR;
395400
$this->writeFrame(\pack("N", $error), Http2Parser::RST_STREAM, Http2Parser::NO_FLAG, $id);
396401
$this->releaseStream($id, $exception ?? new ClientException($this->client, "Stream error", $error));

0 commit comments

Comments
 (0)