diff --git a/Response/AsyncResponse.php b/Response/AsyncResponse.php index 0752bff..9f8f65b 100644 --- a/Response/AsyncResponse.php +++ b/Response/AsyncResponse.php @@ -65,7 +65,7 @@ public function __construct(HttpClientInterface $client, string $method, string while (true) { foreach (self::stream([$response], $timeout) as $chunk) { if ($chunk->isTimeout() && $response->passthru) { - foreach (self::passthru($response->client, $response, new ErrorChunk($response->offset, new TransportException($chunk->getError()))) as $chunk) { + foreach (self::passthru($response->client, $response, new ErrorChunk($response->offset, $chunk->getError())) as $chunk) { if ($chunk->isFirst()) { return false; } diff --git a/Response/CurlResponse.php b/Response/CurlResponse.php index 94db1d7..a085422 100644 --- a/Response/CurlResponse.php +++ b/Response/CurlResponse.php @@ -98,7 +98,6 @@ public function __construct(CurlClientState $multi, \CurlHandle|string $ch, ?arr $this->info['pause_handler'] = static function (float $duration) use ($ch, $multi, $execCounter) { if (0 < $duration) { if ($execCounter === $multi->execCounter) { - $multi->execCounter = !\is_float($execCounter) ? 1 + $execCounter : \PHP_INT_MIN; curl_multi_remove_handle($multi->handle, $ch); } diff --git a/Tests/RetryableHttpClientTest.php b/Tests/RetryableHttpClientTest.php index b32601a..4a3f71a 100644 --- a/Tests/RetryableHttpClientTest.php +++ b/Tests/RetryableHttpClientTest.php @@ -13,6 +13,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\HttpClient\Exception\ServerException; +use Symfony\Component\HttpClient\Exception\TimeoutException; use Symfony\Component\HttpClient\HttpClient; use Symfony\Component\HttpClient\MockHttpClient; use Symfony\Component\HttpClient\NativeHttpClient; @@ -21,6 +22,7 @@ use Symfony\Component\HttpClient\Retry\GenericRetryStrategy; use Symfony\Component\HttpClient\RetryableHttpClient; use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; +use Symfony\Contracts\HttpClient\Test\TestHttpServer; class RetryableHttpClientTest extends TestCase { @@ -245,6 +247,35 @@ public function testRetryOnErrorAssertContent() self::assertSame('Test out content', $response->getContent(), 'Content should be buffered'); } + /** + * @testWith ["GET"] + * ["POST"] + * ["PUT"] + * ["PATCH"] + * ["DELETE"] + */ + public function testRetryOnHeaderTimeout(string $method) + { + $client = HttpClient::create(); + + if ($client instanceof NativeHttpClient) { + $this->markTestSkipped('NativeHttpClient cannot timeout before receiving headers'); + } + + TestHttpServer::start(); + + $client = new RetryableHttpClient($client); + $response = $client->request($method, 'http://localhost:8057/timeout-header', ['timeout' => 0.1]); + + try { + $response->getStatusCode(); + $this->fail(TimeoutException::class.' expected'); + } catch (TimeoutException $e) { + } + + $this->assertSame('Idle timeout reached for "http://localhost:8057/timeout-header".', $response->getInfo('error')); + } + public function testRetryWithMultipleBaseUris() { $client = new RetryableHttpClient(