diff --git a/src/ShoppinPal/Vend/Api/BaseApiAbstract.php b/src/ShoppinPal/Vend/Api/BaseApiAbstract.php index ef0a0ff..d7427c9 100644 --- a/src/ShoppinPal/Vend/Api/BaseApiAbstract.php +++ b/src/ShoppinPal/Vend/Api/BaseApiAbstract.php @@ -5,6 +5,7 @@ use ShoppinPal\Vend\Auth\AuthHelper; use ShoppinPal\Vend\Exception\CommunicationException; use ShoppinPal\Vend\Exception\EntityNotFoundException; +use ShoppinPal\Vend\Exception\RateLimitingException; use YapepBase\Application; use YapepBase\Communication\CurlHttpRequest; @@ -85,19 +86,32 @@ protected function getAuthenticatedRequestForUri($path, array $params = [], $ski * * @return array|null * @throws EntityNotFoundException + * @throws RateLimitingException * @throws CommunicationException */ protected function sendRequest(CurlHttpRequest $request, $requestType) { $result = $request->send(); - if (!$result->getError() && 404 == $result->getResponseCode()) { - throw new EntityNotFoundException('The specified entity can not be found', 404, null, $result); - } - if (!$result->isRequestSuccessful()) { + if (!$result->getError()) { + switch ($result->getResponseCode()) { + case 404: + throw new EntityNotFoundException('The specified entity can not be found', 404, null, $result); + + case 429: + throw new RateLimitingException( + $requestType, + $result, + 'Your access to the API has been rate limited', + 429, + null + ); + } + } + $exceptionClass = $this->getCommunicationExceptionClass(); - throw new $exceptionClass($requestType, $result, 0, null, $result); + throw new $exceptionClass($requestType, $result, 0, null); } if (204 == $result->getResponseCode()) { @@ -108,7 +122,7 @@ protected function sendRequest(CurlHttpRequest $request, $requestType) if (empty($resultData)) { $exceptionClass = $this->getCommunicationExceptionClass(); - throw new $exceptionClass($requestType, $result, 0, null, $result); + throw new $exceptionClass($requestType, $result, 0, null); } return $resultData; diff --git a/src/ShoppinPal/Vend/Exception/CommunicationException.php b/src/ShoppinPal/Vend/Exception/CommunicationException.php index 96668f6..816dafc 100644 --- a/src/ShoppinPal/Vend/Exception/CommunicationException.php +++ b/src/ShoppinPal/Vend/Exception/CommunicationException.php @@ -34,7 +34,7 @@ public function __construct( $this->curlResult = $curlResult; $this->requestType = $requestType; - parent::__construct($message, $code, $previous, $data); + parent::__construct($message, $code, $previous, $data ?: $curlResult); } /** diff --git a/src/ShoppinPal/Vend/Exception/RateLimitingException.php b/src/ShoppinPal/Vend/Exception/RateLimitingException.php new file mode 100644 index 0000000..a991cf3 --- /dev/null +++ b/src/ShoppinPal/Vend/Exception/RateLimitingException.php @@ -0,0 +1,39 @@ +curlResult->getResponseBody(); + $decodedBody = json_decode($responseBody, true); + + if (empty($decodedBody)) { + throw new Exception('Unable to decode response body: ' . $responseBody); + } + + if (!isset($decodedBody['retry-after'])) { + throw new Exception('No retry-after in response body: ' . $responseBody); + } + + $retryAfter = DateTime::createFromFormat(DateTime::RFC822, $decodedBody['retry-after']); + + if (empty($retryAfter)) { + throw new Exception('Unable to parse date from retry-after string: ' . $decodedBody['retry-after']); + } + + return $retryAfter; + } +}