Skip to content

Commit

Permalink
Changed exception code to return the HTTP status codes. Within Except…
Browse files Browse the repository at this point in the history
…ion class now information is provide on how to handle the execution exception with getHandleCode and getHandleText.
  • Loading branch information
drsdre committed Apr 6, 2017
1 parent b3e0f39 commit 4d2a1bc
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 57 deletions.
89 changes: 48 additions & 41 deletions Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use yii\authclient\OAuthToken;
use yii\base\InvalidConfigException;
use yii\base\InvalidParamException;
use yii\httpclient\Response;

/**
* Client for communicating with a Wordpress Rest API interface (standard included from Wordpress 4.7 on).
Expand Down Expand Up @@ -380,100 +381,106 @@ protected function executeRequest() {

do {
try {
// Execute request
// Execute the request
$this->response = $this->request->send();

// Test result
// Test the result
$result_content = Json::decode( $this->response->content, false );

// Check for response status code
// Check if response is valid
if ( ! $this->response->isOk ) {

// Error handling
switch ( $this->response->statusCode ) {
case 304:
throw new Exception(
'Not Modified.'
);
throw new Exception( 'Not Modified.', $this->response->statusCode );
case 400:
// Collect the request parameters
$parameter_errors = [];
foreach($result_content->data->params as $param_error) {
foreach ( $result_content->data->params as $param_error ) {
$parameter_errors[] = $param_error;
}

throw new Exception(
'Bad Request: '.implode(' | ', $parameter_errors).' (request ' . $this->request->getFullUrl() . ').',
Exception::FAIL
'Bad Request: ' . implode( ' | ',
$parameter_errors ) . ' (request ' . $this->request->getFullUrl() . ').',
$this->response->statusCode
);
case 401:
// Nonce used can be retried, other 401 can not
if ( isset( $result_content->code ) && $result_content->code == 'json_oauth1_nonce_already_used' ) {
// Oauth1 nonce already used, can be retried

// Map to status code 432 (unassigned)
throw new Exception(
( isset( $result_content->message ) ? $result_content->message : $this->response->content ) .
' ' . $this->request->getFullUrl(),
Exception::RETRY
);
} else {
throw new Exception(
'Unauthorized: '.$result_content->message.' (request ' . $this->request->getFullUrl() . ').',
Exception::FAIL
432
);
}

// Generic 401 error
throw new Exception(
'Unauthorized: ' . $result_content->message . ' (request ' . $this->request->getFullUrl() . ').',
$this->response->statusCode
);
case 403:
throw new Exception(
'Forbidden: request not authenticated accessing ' . $this->request->getFullUrl(),
Exception::FAIL
'Forbidden: request not allowed accessing ' . $this->request->getFullUrl(),
$this->response->statusCode
);
case 404:
throw new Exception(
'No data found: route ' . $this->request->getFullUrl() . 'does not exist.',
Exception::FAIL
'Not found: ' . $this->request->getFullUrl() . 'does not exist.',
$this->response->statusCode
);
case 405:
throw new Exception(
'Method Not Allowed: incorrect HTTP method ' . $this->request->getMethod() . ' provided.',
Exception::FAIL
$this->response->statusCode
);
case 405:
throw new Exception(
'Gone: resource ' . $this->request->getFullUrl() . ' has moved.',
$this->response->statusCode
);
case 415:
throw new Exception(
'Unsupported Media Type (incorrect HTTP method ' . $this->request->getMethod() . ' provided).',
Exception::FAIL
$this->response->statusCode
);
case 429:
throw new Exception(
'Too many requests: client is rate limited.',
Exception::WAIT_RETRY
$this->response->statusCode
);
case 500:
$content = $this->asArray();
// Check if specific error code have been returned
if ( isset( $content['code'] ) && $content['code'] == 'term_exists' ) {
// Map to status code 433 (unassigned, used for 'item exists' error type)
throw new Exception(
isset( $content['message'] ) ? $content['message'] : 'Internal server error.',
Exception::ITEM_EXISTS
);
} else {
throw new Exception(
'Internal server error.',
Exception::FAIL
433
);
}

throw new Exception( 'Internal server error: ' . $this->response->message, $this->response->statusCode );
case 501:
throw new Exception( 'Not Implemented: ' . $this->request->getFullUrl() . '.',
$this->response->statusCode );
case 502:
throw new Exception(
'Bad Gateway error: server has an issue.',
Exception::RETRY
);
throw new Exception( 'Bad Gateway: server has an issue.',
$this->response->statusCode );
default:
throw new Exception(
'Unknown code ' . $this->response->statusCode . ' for URL ' . $this->request->getFullUrl()
);
throw new Exception( 'Status code ' . $this->response->statusCode . ' returned for URL ' . $this->request->getFullUrl(),
$this->response->statusCode );
}
}
$request_success = true;
} catch (InvalidParamException $e) {
throw new Exception(
'Invalid JSON data returned: ' . $e->getMessage(),
Exception::ILLEGAL_RESPONSE
);
} catch ( InvalidParamException $e ) {
// Handle JSON parsing error
// Map to status code 512 (unassigned, used for 'illegal response')
throw new Exception( 'Invalid JSON data returned: ' . $e->getMessage(), 512 );

} catch ( \yii\httpclient\Exception $e ) {
// Check if call can be retried and max retries is not hit
Expand Down
50 changes: 34 additions & 16 deletions Exception.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,32 +11,50 @@
*/
class Exception extends \yii\base\Exception {

const FAIL = 0;
const RETRY = 1;
const WAIT_RETRY = 2;
const ITEM_EXISTS = 3;
const ILLEGAL_RESPONSE = 4;

static $code_names = [
self::FAIL => ' unrecoverable',
self::RETRY => ' and can be retried',
self::WAIT_RETRY => ' and can be retried after wait time',
self::ITEM_EXISTS => ' because item already exists',
self::ILLEGAL_RESPONSE => ' with an illegal JSON response',
const HANDLE_AS_FAIL = 0;
const HANDLE_AS_RETRY = 1;
const HANDLE_AS_WAIT_RETRY = 2;
const HANDLE_AS_ITEM_EXISTS = 3;
const HANDLE_AS_ITEM_NOT_FOUND = 4;
const HANDLE_AS_ILLEGAL_RESPONSE = 4;

static $handle_names = [
self::HANDLE_AS_FAIL => 'unrecoverable',
self::HANDLE_AS_RETRY => 'can be retried',
self::HANDLE_AS_WAIT_RETRY => 'can be retried after wait time',
self::HANDLE_AS_ITEM_NOT_FOUND => 'item is not found',
self::HANDLE_AS_ITEM_EXISTS => 'item already exists',
self::HANDLE_AS_ILLEGAL_RESPONSE => 'illegal JSON response',
];

static $code_handle_mappings = [
404 => self::HANDLE_AS_ITEM_NOT_FOUND,
429 => self::HANDLE_AS_WAIT_RETRY,
432 => self::HANDLE_AS_RETRY,
433 => self::HANDLE_AS_ITEM_EXISTS,
502 => self::HANDLE_AS_RETRY,
512 => self::HANDLE_AS_ILLEGAL_RESPONSE,
];

/**
* @return string the user-friendly name of this exception
*/
public function getName()
{
return 'API request failed'.$this->getCodeName();
return "API request failed (#{$this->getCode()}): {$this->getMessage()}. To be handled as {$this->getHandleText()}";
}

/**
* @return int
*/
public function getHandleCode() {
return isset(self::$code_handle_mappings[$this->getCode()])?self::$code_handle_mappings[$this->getCode()]:self::HANDLE_AS_FAIL;
}

/**
* @return mixed|string
* @return string
*/
public function getCodeName() {
return isset(self::$code_names[$this->getCode()])?self::$code_names[$this->getCode()]:'';
public function getHandleText() {
return self::$handle_names[$this->getHandleCode()];
}
}

0 comments on commit 4d2a1bc

Please sign in to comment.