8000 [HttpClient] Fix buffering AsyncResponse with no passthru by nicolas-grekas · Pull Request #59689 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[HttpClient] Fix buffering AsyncResponse with no passthru #59689

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 5 additions & 12 deletions src/Symfony/Component/HttpClient/Response/AsyncResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
namespace Symfony\Component\HttpClient\Response;

use Symfony\Component\HttpClient\Chunk\ErrorChunk;
use Symfony\Component\HttpClient\Chunk\FirstChunk;
use Symfony\Component\HttpClient\Chunk\LastChunk;
use Symfony\Component\HttpClient\Exception\TransportException;
use Symfony\Contracts\HttpClient\ChunkInterface;
Expand Down Expand Up @@ -245,7 +244,7 @@ public static function stream(iterable $responses, ?float $timeout = null, ?stri
$wrappedResponses[] = $r->response;

if ($r->stream) {
yield from self::passthruStream($response = $r->response, $r, new FirstChunk(), $asyncMap);
yield from self::passthruStream($response = $r->response, $r, $asyncMap, new LastChunk());

if (!isset($asyncMap[$response])) {
array_pop($wrappedResponses);
Expand Down Expand Up @@ -276,15 +275,9 @@ public static function stream(iterable $responses, ?float $timeout = null, ?stri
}

if (!$r->passthru) {
if (null !== $chunk->getError() || $chunk->isLast()) {
unset($asyncMap[$response]);
} elseif (null !== $r->content && '' !== ($content = $chunk->getContent()) && \strlen($content) !== fwrite($r->content, $content)) {
$chunk = new ErrorChunk($r->offset, new TransportException(sprintf('Failed writing %d bytes to the response buffer.', \strlen($content))));
$r->info['error'] = $chunk->getError();
$r->response->cancel();
}
$r->stream = (static fn () => yield $chunk)();
yield from self::passthruStream($response, $r, $asyncMap);

yield $r => $chunk;
continue;
}

Expand Down Expand Up @@ -347,13 +340,13 @@ private static function passthru(HttpClientInterface $client, self $r, ChunkInte
}
$r->stream = $stream;

yield from self::passthruStream($response, $r, null, $asyncMap);
yield from self::passthruStream($response, $r, $asyncMap);
}

/**
* @param \SplObjectStorage<ResponseInterface, AsyncResponse>|null $asyncMap
*/
private static function passthruStream(ResponseInterface $response, self $r, ?ChunkInterface $chunk, ?\SplObjectStorage $asyncMap): \Generator
private static function passthruStream(ResponseInterface $response, self $r, ?\SplObjectStorage $asyncMap, ?ChunkInterface $chunk = null): \Generator
{
while (true) {
try {
Expand Down
14 changes: 14 additions & 0 deletions src/Symfony/Component/HttpClient/Tests/AsyncDecoratorTraitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,20 @@ public function testBufferPurePassthru()

$this->assertStringContainsString('SERVER_PROTOCOL', $response->getContent());
$this->assertStringContainsString('HTTP_HOST', $response->getContent());

$client = new class(parent::getHttpClient(__FUNCTION__)) implements HttpClientInterface {
use AsyncDecoratorTrait;

public function request(string $method, string $url, array $options = []): ResponseInterface
{
return new AsyncResponse($this->client, $method, $url, $options);
}
};

$response = $client->request('GET', 'http://localhost:8057/');

$this->assertStringContainsString('SERVER_PROTOCOL', $response->getContent());
$this->assertStringContainsString('HTTP_HOST', $response->getContent());
}

public function testRetryTimeout()
Expand Down
Loading
0