From 496ba59b4f667391d5b044a904664e26253bbaea Mon Sep 17 00:00:00 2001 From: Daniel Burger <48986191+danielburger1337@users.noreply.github.com> Date: Thu, 4 May 2023 19:29:09 +0200 Subject: [PATCH] [HttpClient] Add `max_retries` option to `RetryableHttpClient` --- src/Symfony/Component/HttpClient/CHANGELOG.md | 5 +++ .../HttpClient/RetryableHttpClient.php | 12 ++++-- .../Tests/RetryableHttpClientTest.php | 41 +++++++++++++++++++ 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/HttpClient/CHANGELOG.md b/src/Symfony/Component/HttpClient/CHANGELOG.md index 7cd69191c5411..0d483c645c9da 100644 --- a/src/Symfony/Component/HttpClient/CHANGELOG.md +++ b/src/Symfony/Component/HttpClient/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +6.4 +--- + + * Add `max_retries` option to `RetryableHttpClient` to adjust the retry logic on a per request level + 6.3 --- diff --git a/src/Symfony/Component/HttpClient/RetryableHttpClient.php b/src/Symfony/Component/HttpClient/RetryableHttpClient.php index 1a6ec7d35e63f..bb0cab1b3ca6b 100644 --- a/src/Symfony/Component/HttpClient/RetryableHttpClient.php +++ b/src/Symfony/Component/HttpClient/RetryableHttpClient.php @@ -60,6 +60,9 @@ public function withOptions(array $options): static } $clone = clone $this; + $clone->maxRetries = (int) ($options['max_retries'] ?? $this->maxRetries); + unset($options['max_retries']); + $clone->client = $this->client->withOptions($options); return $clone; @@ -71,11 +74,14 @@ public function request(string $method, string $url, array $options = []): Respo $baseUris = \is_array($baseUris) ? $baseUris : []; $options = self::shiftBaseUri($options, $baseUris); - if ($this->maxRetries <= 0) { + $maxRetries = (int) ($options['max_retries'] ?? $this->maxRetries); + unset($options['max_retries']); + + if ($maxRetries <= 0) { return new AsyncResponse($this->client, $method, $url, $options); } - return new AsyncResponse($this->client, $method, $url, $options, function (ChunkInterface $chunk, AsyncContext $context) use ($method, $url, $options, &$baseUris) { + return new AsyncResponse($this->client, $method, $url, $options, function (ChunkInterface $chunk, AsyncContext $context) use ($method, $url, $options, $maxRetries, &$baseUris) { static $retryCount = 0; static $content = ''; static $firstChunk; @@ -152,7 +158,7 @@ public function request(string $method, string $url, array $options = []): Respo $context->replaceRequest($method, $url, self::shiftBaseUri($options, $baseUris)); $context->pause($delay / 1000); - if ($retryCount >= $this->maxRetries) { + if ($retryCount >= $maxRetries) { $context->passthru(); } }); diff --git a/src/Symfony/Component/HttpClient/Tests/RetryableHttpClientTest.php b/src/Symfony/Component/HttpClient/Tests/RetryableHttpClientTest.php index b32601aefc5a5..2ef52336c340c 100644 --- a/src/Symfony/Component/HttpClient/Tests/RetryableHttpClientTest.php +++ b/src/Symfony/Component/HttpClient/Tests/RetryableHttpClientTest.php @@ -344,4 +344,45 @@ public function testRetryWithMultipleBaseUrisPreservesNonNestedOrder() self::assertSame(200, $response->getStatusCode()); self::assertSame('http://example.com/d/foo-bar', $response->getInfo('url')); } + + public function testMaxRetriesOption() + { + $client = new RetryableHttpClient( + new MockHttpClient([ + new MockResponse('', ['http_code' => 500]), + new MockResponse('', ['http_code' => 502]), + new MockResponse('', ['http_code' => 200]), + ]), + new GenericRetryStrategy([500, 502], 0), + 3 + ); + + $response = $client->request('GET', 'http://example.com/foo-bar', [ + 'max_retries' => 1, + ]); + + self::assertSame(502, $response->getStatusCode()); + } + + public function testMaxRetriesWithOptions() + { + $client = new RetryableHttpClient( + new MockHttpClient([ + new MockResponse('', ['http_code' => 500]), + new MockResponse('', ['http_code' => 502]), + new MockResponse('', ['http_code' => 504]), + new MockResponse('', ['http_code' => 200]), + ]), + new GenericRetryStrategy([500, 502, 504], 0), + 3 + ); + + $client = $client->withOptions([ + 'max_retries' => 2, + ]); + + $response = $client->request('GET', 'http://example.com/foo-bar'); + + self::assertSame(504, $response->getStatusCode()); + } }
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: