Skip to content

Commit fc70c5e

Browse files
Fix Http::retry so that throw is respected for call signature Http::retry([1,2], throw: false) (#52002)
* Update HttpClientTest.php * Fix PendingRequest.php to deal with tries as an array * Style CI spaces * formatting --------- Co-authored-by: Taylor Otwell <[email protected]>
1 parent 500d93a commit fc70c5e

File tree

2 files changed

+145
-2
lines changed

2 files changed

+145
-2
lines changed

src/Illuminate/Http/Client/PendingRequest.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -911,11 +911,15 @@ public function send(string $method, string $url, array $options = [])
911911
$response->throw($this->throwCallback);
912912
}
913913

914-
if ($attempt < $this->tries && $shouldRetry) {
914+
$potentialTries = is_array($this->tries)
915+
? count($this->tries) + 1
916+
: $this->tries;
917+
918+
if ($attempt < $potentialTries && $shouldRetry) {
915919
$response->throw();
916920
}
917921

918-
if ($this->tries > 1 && $this->retryThrow) {
922+
if ($potentialTries > 1 && $this->retryThrow) {
919923
$response->throw();
920924
}
921925
}

tests/Http/HttpClientTest.php

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1711,6 +1711,28 @@ public function testRequestExceptionIsThrownWhenRetriesExhausted()
17111711
$this->factory->assertSentCount(2);
17121712
}
17131713

1714+
public function testRequestExceptionIsThrownWhenRetriesExhaustedWithBackoffArray()
1715+
{
1716+
$this->factory->fake([
1717+
'*' => $this->factory->response(['error'], 403),
1718+
]);
1719+
1720+
$exception = null;
1721+
1722+
try {
1723+
$this->factory
1724+
->retry([1], 0, null, true)
1725+
->get('http://foo.com/get');
1726+
} catch (RequestException $e) {
1727+
$exception = $e;
1728+
}
1729+
1730+
$this->assertNotNull($exception);
1731+
$this->assertInstanceOf(RequestException::class, $exception);
1732+
1733+
$this->factory->assertSentCount(2);
1734+
}
1735+
17141736
public function testRequestExceptionIsThrownWithoutRetriesIfRetryNotNecessary()
17151737
{
17161738
$this->factory->fake([
@@ -1740,6 +1762,35 @@ public function testRequestExceptionIsThrownWithoutRetriesIfRetryNotNecessary()
17401762
$this->factory->assertSentCount(1);
17411763
}
17421764

1765+
public function testRequestExceptionIsThrownWithoutRetriesIfRetryNotNecessaryWithBackoffArray()
1766+
{
1767+
$this->factory->fake([
1768+
'*' => $this->factory->response(['error'], 500),
1769+
]);
1770+
1771+
$exception = null;
1772+
$whenAttempts = 0;
1773+
1774+
try {
1775+
$this->factory
1776+
->retry([1000, 1000], 1000, function ($exception) use (&$whenAttempts) {
1777+
$whenAttempts++;
1778+
1779+
return $exception->response->status() === 403;
1780+
}, true)
1781+
->get('http://foo.com/get');
1782+
} catch (RequestException $e) {
1783+
$exception = $e;
1784+
}
1785+
1786+
$this->assertNotNull($exception);
1787+
$this->assertInstanceOf(RequestException::class, $exception);
1788+
1789+
$this->assertSame(1, $whenAttempts);
1790+
1791+
$this->factory->assertSentCount(1);
1792+
}
1793+
17431794
public function testRequestExceptionIsNotThrownWhenDisabledAndRetriesExhausted()
17441795
{
17451796
$this->factory->fake([
@@ -1755,6 +1806,21 @@ public function testRequestExceptionIsNotThrownWhenDisabledAndRetriesExhausted()
17551806
$this->factory->assertSentCount(2);
17561807
}
17571808

1809+
public function testRequestExceptionIsNotThrownWhenDisabledAndRetriesExhaustedWithBackoffArray()
1810+
{
1811+
$this->factory->fake([
1812+
'*' => $this->factory->response(['error'], 403),
1813+
]);
1814+
1815+
$response = $this->factory
1816+
->retry([1, 2], throw: false)
1817+
->get('http://foo.com/get');
1818+
1819+
$this->assertTrue($response->failed());
1820+
1821+
$this->factory->assertSentCount(3);
1822+
}
1823+
17581824
public function testRequestExceptionIsNotThrownWithoutRetriesIfRetryNotNecessary()
17591825
{
17601826
$this->factory->fake([
@@ -1778,6 +1844,29 @@ public function testRequestExceptionIsNotThrownWithoutRetriesIfRetryNotNecessary
17781844
$this->factory->assertSentCount(1);
17791845
}
17801846

1847+
public function testRequestExceptionIsNotThrownWithoutRetriesIfRetryNotNecessaryWithBackoffArray()
1848+
{
1849+
$this->factory->fake([
1850+
'*' => $this->factory->response(['error'], 500),
1851+
]);
1852+
1853+
$whenAttempts = 0;
1854+
1855+
$response = $this->factory
1856+
->retry([1, 2], 0, function ($exception) use (&$whenAttempts) {
1857+
$whenAttempts++;
1858+
1859+
return $exception->response->status() === 403;
1860+
}, false)
1861+
->get('http://foo.com/get');
1862+
1863+
$this->assertTrue($response->failed());
1864+
1865+
$this->assertSame(1, $whenAttempts);
1866+
1867+
$this->factory->assertSentCount(1);
1868+
}
1869+
17811870
public function testRequestCanBeModifiedInRetryCallback()
17821871
{
17831872
$this->factory->fake([
@@ -1803,6 +1892,31 @@ public function testRequestCanBeModifiedInRetryCallback()
18031892
});
18041893
}
18051894

1895+
public function testRequestCanBeModifiedInRetryCallbackWithBackoffArray()
1896+
{
1897+
$this->factory->fake([
1898+
'*' => $this->factory->sequence()
1899+
->push(['error'], 500)
1900+
->push(['ok'], 200),
1901+
]);
1902+
1903+
$response = $this->factory
1904+
->retry([2], when: function ($exception, $request) {
1905+
$this->assertInstanceOf(PendingRequest::class, $request);
1906+
1907+
$request->withHeaders(['Foo' => 'Bar']);
1908+
1909+
return true;
1910+
}, throw: false)
1911+
->get('http://foo.com/get');
1912+
1913+
$this->assertTrue($response->successful());
1914+
1915+
$this->factory->assertSent(function (Request $request) {
1916+
return $request->hasHeader('Foo') && $request->header('Foo') === ['Bar'];
1917+
});
1918+
}
1919+
18061920
public function testExceptionThrownInRetryCallbackWithoutRetrying()
18071921
{
18081922
$this->factory->fake([
@@ -1828,6 +1942,31 @@ public function testExceptionThrownInRetryCallbackWithoutRetrying()
18281942
$this->factory->assertSentCount(1);
18291943
}
18301944

1945+
public function testExceptionThrownInRetryCallbackWithoutRetryingWithBackoffArray()
1946+
{
1947+
$this->factory->fake([
1948+
'*' => $this->factory->response(['error'], 500),
1949+
]);
1950+
1951+
$exception = null;
1952+
1953+
try {
1954+
$this->factory
1955+
->retry([1, 2, 3], when: function ($exception) use (&$whenAttempts) {
1956+
throw new Exception('Foo bar');
1957+
}, throw: false)
1958+
->get('http://foo.com/get');
1959+
} catch (Exception $e) {
1960+
$exception = $e;
1961+
}
1962+
1963+
$this->assertNotNull($exception);
1964+
$this->assertInstanceOf(Exception::class, $exception);
1965+
$this->assertEquals('Foo bar', $exception->getMessage());
1966+
1967+
$this->factory->assertSentCount(1);
1968+
}
1969+
18311970
public function testRequestsWillBeWaitingSleepMillisecondsReceivedBeforeRetry()
18321971
{
18331972
Sleep::fake();

0 commit comments

Comments
 (0)