Skip to content

Commit a5ff19e

Browse files
committed
Merge pull request #23 from gurubobnz/master
Support for "Too Many Requests" 429 response from Vend
2 parents dd32515 + 1ef732f commit a5ff19e

2 files changed

Lines changed: 43 additions & 5 deletions

File tree

src/VendAPI/VendAPI.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,13 @@ class VendAPI
4444
*/
4545
public $default_outlet = 'Main Outlet';
4646

47+
/**
48+
* If rate limiting kicks in and the retry-after date is earlier than the current system time
49+
* then this API will sleep for 60 seconds, otherwise an exception will be thrown.
50+
* The right thing to do is ensure that your system has its time synchronised with a time server.
51+
*/
52+
public $allow_time_slip = false;
53+
4754
/**
4855
* @param string $url url of your shop eg https://shopname.vendhq.com
4956
* @param string $tokenType tokenType for api
@@ -111,6 +118,7 @@ public function getSales($options = array())
111118
$path = '';
112119
if (count($options)) {
113120
foreach ($options as $k => $v) {
121+
$v = urlencode($v); // ensure values with spaces etc are encoded properly
114122
$path .= '/'.$k.'/'.$v;
115123
}
116124
}
@@ -273,6 +281,34 @@ private function _request($path, $data = null, $depage = null)
273281
throw new Exception("Error: Recieved null result from API");
274282
}
275283

284+
// Check for 400+ error:
285+
if($this->requestr->http_code >= 400) {
286+
if($this->requestr->http_code == 429) { // Too Many Requests
287+
$retry_after = strtotime($result->{'retry-after'});
288+
if($retry_after < time()) {
289+
if($this->allow_time_slip) {
290+
// The date on the current machine must be out of sync ... sleep for a minute to give the API time to cool down
291+
sleep(60);
292+
} else {
293+
throw new Exception("Rate limit hit on API yet retry-after time given is in the past. Please check time of local system. Set \$allow-time-slip to true to work around this problem");
294+
}
295+
}
296+
if($this->debug) {
297+
echo "Vend API rate limit hit\n";
298+
echo "Time now on local system is ".date('r',time())."\n";
299+
echo "Sleeping until ".date('r', $retry_after)." (as advised by Vend API) ";
300+
}
301+
while(time() < $retry_after) {
302+
sleep(1);
303+
if($this->debug) { echo "."; }
304+
}
305+
306+
// We've given the Vend API time to cool down - retry the original request:
307+
return $this->_request($path, $data, $depage);
308+
}
309+
throw new Exception("Error: Unexpected HTTP ".$this->requestr->http_code." result from API");
310+
}
311+
276312
if ($depage && isset($result->pagination) && $result->pagination->page == 1) {
277313
for ($i=2; $i <= $result->pagination->pages; $i++) {
278314
$paged_result = $this->_request(rtrim($path, '/').'/page/'.$i, $data, false);

src/VendAPI/VendRequest.php

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ class VendRequest
2525
private $http_header;
2626
private $http_body;
2727

28+
public $http_code;
29+
2830
public function __construct($url, $username, $password)
2931
{
3032
$this->curl = curl_init();
@@ -35,7 +37,7 @@ public function __construct($url, $username, $password)
3537
$options = array(
3638
CURLOPT_RETURNTRANSFER => 1,
3739
CURLOPT_TIMEOUT => 120,
38-
CURLOPT_FAILONERROR => 1,
40+
CURLOPT_FAILONERROR => 0, // 0 allows us to process the 400 responses (e.g. rate limits)
3941
CURLOPT_HTTPAUTH => CURLAUTH_ANY,
4042
CURLOPT_HTTPHEADER => array(
4143
'Accept: application/json',
@@ -102,15 +104,15 @@ private function _request($path, $type)
102104
$this->setOpt(CURLOPT_URL, $this->url.$path);
103105

104106
$this->response = $response = curl_exec($this->curl);
105-
106-
$header_size = curl_getinfo($this->curl, CURLINFO_HEADER_SIZE);
107+
$curl_status = curl_getinfo($this->curl);
108+
$this->http_code = $curl_status['http_code'];
109+
$header_size = $curl_status['header_size'];
107110

108111
$this->http_header = substr($response, 0, $header_size);
109112
$this->http_body = substr($response, $header_size);
110113

111-
112114
if ($this->debug) {
113-
$this->curl_debug = curl_getinfo($this->curl);
115+
$this->curl_debug = $status;
114116
$head = $foot = "\n";
115117
if (php_sapi_name() !== 'cli') {
116118
$head = '<pre>';

0 commit comments

Comments
 (0)