bug #40080 Fix Request with DNS issue not retried (jderusse)

This PR was merged into the 5.2 branch.

Discussion
----------

Fix Request with DNS issue not retried

| Q             | A
| ------------- | ---
| Branch?       | 5.2
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | fix #
| License       | MIT
| Doc PR        | -

When the client failed to resolve the DNS, the RetryableHttpClient should retry the request. But because `$chunk->isLast()` is used later, the original exception is thrown.

/cc @nikophil

Commits
-------

216abd0307 Fix Request with DNS issue not retried
This commit is contained in:
Nicolas Grekas 2021-02-04 13:01:57 +01:00
commit 854eabdfe4
2 changed files with 27 additions and 1 deletions

View File

@ -127,7 +127,7 @@ class RetryableHttpClient implements HttpClientInterface
$context->getResponse()->cancel();
$delay = $this->getDelayFromHeader($context->getHeaders()) ?? $this->strategy->getDelay($context, $chunk->isLast() ? $content : null, $exception);
$delay = $this->getDelayFromHeader($context->getHeaders()) ?? $this->strategy->getDelay($context, !$exception && $chunk->isLast() ? $content : null, $exception);
++$retryCount;
$this->logger->info('Try #{count} after {delay}ms'.($exception ? ': '.$exception->getMessage() : ', status code: '.$context->getStatusCode()), [

View File

@ -5,6 +5,7 @@ namespace Symfony\Component\HttpClient\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpClient\Exception\ServerException;
use Symfony\Component\HttpClient\MockHttpClient;
use Symfony\Component\HttpClient\NativeHttpClient;
use Symfony\Component\HttpClient\Response\AsyncContext;
use Symfony\Component\HttpClient\Response\MockResponse;
use Symfony\Component\HttpClient\Retry\GenericRetryStrategy;
@ -133,4 +134,29 @@ class RetryableHttpClientTest extends TestCase
}
}
}
public function testRetryWithDnsIssue()
{
$client = new RetryableHttpClient(
new NativeHttpClient(),
new class(GenericRetryStrategy::DEFAULT_RETRY_STATUS_CODES, 0) extends GenericRetryStrategy {
public function shouldRetry(AsyncContext $context, ?string $responseContent, ?TransportExceptionInterface $exception): ?bool
{
$this->fail('should not be called');
}
},
2,
$logger = new TestLogger()
);
$response = $client->request('GET', 'http://does.not.exists/foo-bar');
try {
$response->getHeaders();
} catch (TransportExceptionInterface $e) {
$this->assertSame('Could not resolve host "does.not.exists".', $e->getMessage());
}
$this->assertCount(2, $logger->logs);
$this->assertSame('Try #{count} after {delay}ms: Could not resolve host "does.not.exists".', $logger->logs[0]);
}
}