Skip to content

Commit 5fe8903

Browse files
committed
Add support for automatically retrying rate limited requests
1 parent cdbba9b commit 5fe8903

File tree

4 files changed

+53
-3
lines changed

4 files changed

+53
-3
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ This is a PHP wrapper for [Spotify's Web API](https://developer.spotify.com/web-
1414
* User playback control.
1515
* Authorization flow helpers.
1616
* Automatic refreshing of access tokens.
17+
* Automatic retry of rate limited requests.
1718
* PSR-4 autoloading support.
1819

1920
## Requirements

docs/examples/handling-errors.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ try {
1515
When an authentication error occurs, a `SpotifyWebAPIAuthException` will be thrown. This will contain the same properties as above.
1616

1717
## Handling rate limit errors
18+
_As of version `2.12.0` it's possible to automatically retry rate limited requests by setting the `auto_retry` option to `true`._
19+
1820
If your application should hit the Spotify API rate limit, you will get an error back and the number of seconds you need to wait before sending another request.
1921

2022
Here's an example of how to handle this:
@@ -24,7 +26,7 @@ try {
2426
$track = $api->getTrack('7EjyzZcbLxW7PaaLua9Ksb');
2527
} catch (SpotifyWebAPIException $e) {
2628
if ($e->getCode() == 429) { // 429 is Too Many Requests
27-
$lastResponse = $api->getRequest()->getLastResponse(); // Note "getRequest()" since $api->getLastResponse() won't be set
29+
$lastResponse = $api->getRequest()->getLastResponse();
2830

2931
$retryAfter = $lastResponse['headers']['Retry-After']; // Number of seconds to wait before sending another request
3032
} else {
@@ -33,4 +35,4 @@ try {
3335
}
3436
```
3537

36-
Read more about the exact mechanics of rate limiting in the [Spotify API docs](https://developer.spotify.com/web-api/user-guide/#rate-limiting).
38+
Read more about the exact mechanics of rate limiting in the [Spotify API docs](https://developer.spotify.com/documentation/web-api/#rate-limiting).

src/SpotifyWebAPI.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ class SpotifyWebAPI
1010
protected $lastResponse = [];
1111
protected $options = [
1212
'auto_refresh' => false,
13+
'auto_retry' => false,
1314
];
1415
protected $request = null;
1516
protected $session = null;
@@ -80,6 +81,13 @@ protected function sendRequest($method, $uri, $parameters = [], $headers = [])
8081

8182
$headers = $this->authHeaders($headers);
8283

84+
return $this->sendRequest($method, $uri, $parameters, $headers);
85+
} elseif ($this->options['auto_retry'] && $e->isRateLimited()) {
86+
$lastResponse = $this->request->getLastResponse();
87+
$retryAfter = (int) $lastResponse['headers']['Retry-After'];
88+
89+
sleep($retryAfter);
90+
8391
return $this->sendRequest($method, $uri, $parameters, $headers);
8492
}
8593

tests/SpotifyWebAPITest.php

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ class SpotifyWebAPITest extends PHPUnit\Framework\TestCase
66
private function setupStub($expectedMethod, $expectedUri, $expectedParameters, $expectedHeaders, $expectedReturn)
77
{
88
$stub = $this->getMockBuilder('Request')
9-
->setMethods(['api'])
9+
->setMethods(['api', 'getLastResponse'])
1010
->getMock();
1111

1212
$stub->expects($this->any())
@@ -72,6 +72,45 @@ public function testAutoRefreshOption()
7272
$this->assertObjectHasAttribute('id', $response);
7373
}
7474

75+
public function testAutoRetryOption()
76+
{
77+
$headers = [
78+
'Authorization' => 'Bearer ' . $this->accessToken,
79+
];
80+
81+
$return = [
82+
'body' => get_fixture('track'),
83+
'headers' => [
84+
'Retry-After' => 3,
85+
],
86+
'status' => 429,
87+
];
88+
89+
$stub = $this->setupStub(
90+
'GET',
91+
'/v1/tracks/0eGsygTp906u18L0Oimnem',
92+
[],
93+
$headers,
94+
$return
95+
);
96+
97+
$stub->expects($this->at(0))
98+
->method('api')
99+
->willThrowException(
100+
new SpotifyWebAPI\SpotifyWebAPIException('API rate limit exceeded', 429)
101+
);
102+
103+
$api = new SpotifyWebAPI\SpotifyWebAPI($stub);
104+
$api->setAccessToken($this->accessToken);
105+
$api->setOptions([
106+
'auto_retry' => true,
107+
]);
108+
109+
$response = $api->getTrack('0eGsygTp906u18L0Oimnem');
110+
111+
$this->assertObjectHasAttribute('id', $response);
112+
}
113+
75114
public function testAddMyAlbums()
76115
{
77116
$albums = [

0 commit comments

Comments
 (0)