[HttpClient] fix decorating timeout errors

This commit is contained in:
Nicolas Grekas 2020-10-11 17:05:16 +02:00
parent 559ebe35fe
commit 84cda3f02b
2 changed files with 37 additions and 1 deletions

View File

@ -45,7 +45,25 @@ final class AsyncResponse implements ResponseInterface, StreamableInterface
$this->response = $client->request($method, $url, ['buffer' => false] + $options);
$this->passthru = $passthru;
$this->initializer = static function (self $response) {
return null !== $response->shouldBuffer;
if (null === $response->shouldBuffer) {
return false;
}
foreach (self::stream([$response]) as $chunk) {
if ($chunk->isTimeout() && $response->passthru) {
foreach (self::passthru($response->client, $response, new ErrorChunk($response->offset, new TransportException($chunk->getError()))) as $chunk) {
return !$chunk->isFirst();
}
return true;
}
if ($chunk->isFirst()) {
break;
}
}
return false;
};
if (\array_key_exists('user_data', $options)) {
$this->info['user_data'] = $options['user_data'];

View File

@ -212,4 +212,22 @@ class AsyncDecoratorTraitTest extends NativeHttpClientTest
$this->assertStringContainsString('SERVER_PROTOCOL', $response->getContent());
$this->assertStringContainsString('HTTP_HOST', $response->getContent());
}
public function testRetryTimeout()
{
$client = $this->getHttpClient(__FUNCTION__, function (ChunkInterface $chunk, AsyncContext $context) {
try {
$this->assertTrue($chunk->isTimeout());
yield $chunk;
} catch (TransportExceptionInterface $e) {
$context->passthru();
$context->getResponse()->cancel();
$context->replaceRequest('GET', 'http://localhost:8057/timeout-header', ['timeout' => 1]);
}
});
$response = $client->request('GET', 'http://localhost:8057/timeout-header', ['timeout' => 0.1]);
$this->assertSame(200, $response->getStatusCode());
}
}