Skip to content
This repository has been archived by the owner on Sep 24, 2018. It is now read-only.

Commit

Permalink
Merge pull request #461 from WP-API/json-error-reporting
Browse files Browse the repository at this point in the history
Check for JSON encoding/decoding errors
  • Loading branch information
rachelbaker committed Aug 29, 2014
2 parents 39de5d8 + ce4d3ed commit 04ce8e3
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 0 deletions.
33 changes: 33 additions & 0 deletions lib/class-wp-json-server.php
Expand Up @@ -285,6 +285,13 @@ public function serve_request( $path = null ) {

$result = json_encode( $this->prepare_response( $result ) );

$json_error_message = $this->get_json_last_error();
if ( $json_error_message ) {
$json_error_obj = new WP_Error( 'json_encode_error', $json_error_message, array( 'status' => 500 ) );
$result = $this->error_to_response( $json_error_obj );
$result = json_encode( $result->data[0] );
}

if ( isset( $_GET['_jsonp'] ) ) {
// Prepend '/**/' to mitigate possible JSONP Flash attacks
// http://miki.it/blog/2014/7/8/abusing-jsonp-with-rosetta-flash/
Expand Down Expand Up @@ -390,6 +397,12 @@ public function dispatch() {
if ( $supported & self::ACCEPT_JSON ) {
$data = json_decode( $this->get_raw_data(), true );

// test for json_decode() error
$json_error_message = $this->get_json_last_error();
if ( $json_error_message ) {
return new WP_Error( 'json_decode_error', $json_error_message, array( 'status' => 500 ) );
}

if ( $data !== null ) {
$args = array_merge( $args, array( 'data' => $data ) );
}
Expand Down Expand Up @@ -427,6 +440,26 @@ public function dispatch() {
return new WP_Error( 'json_no_route', __( 'No route was found matching the URL and request method' ), array( 'status' => 404 ) );
}

/**
* Returns if an error occurred during most recent JSON encode/decode
* Strings to be translated will be in format like "Encoding error: Maximum stack depth exceeded"
*
* @return boolean|string Boolean false or string error message
*/
protected function get_json_last_error( ) {
// see https://core.trac.wordpress.org/ticket/27799
if ( ! function_exists( 'json_last_error' ) ) {
return false;
}

$last_error_code = json_last_error();
if ( ( defined( 'JSON_ERROR_NONE' ) && $last_error_code === JSON_ERROR_NONE ) || empty( $last_error_code ) ) {
return false;
}

return json_last_error_msg();
}

/**
* Sort parameters by order specified in method declaration
*
Expand Down
53 changes: 53 additions & 0 deletions plugin.php
Expand Up @@ -697,3 +697,56 @@ function json_handle_options_request( $response, $handler ) {

return $response;
}

if ( ! function_exists( 'json_last_error_msg' ) ):
/**
* Returns the error string of the last json_encode() or json_decode() call
*
* @internal This is a compatibility function for PHP <5.5
*
* @return boolean|string Returns the error message on success, "No Error" if no error has occurred, or FALSE on failure.
*/
function json_last_error_msg() {
// see https://core.trac.wordpress.org/ticket/27799
if ( ! function_exists( 'json_last_error' ) ) {
return false;
}

$last_error_code = json_last_error();

// just in case JSON_ERROR_NONE is not defined
$error_code_none = defined( 'JSON_ERROR_NONE' ) ? JSON_ERROR_NONE : 0;

switch ( true ) {
case $last_error_code === $error_code_none:
return 'No error';

case defined( 'JSON_ERROR_DEPTH' ) && JSON_ERROR_DEPTH === $last_error_code:
return 'Maximum stack depth exceeded';

case defined( 'JSON_ERROR_STATE_MISMATCH' ) && JSON_ERROR_STATE_MISMATCH === $last_error_code:
return 'State mismatch (invalid or malformed JSON)';

case defined( 'JSON_ERROR_CTRL_CHAR' ) && JSON_ERROR_CTRL_CHAR === $last_error_code:
return 'Control character error, possibly incorrectly encoded';

case defined( 'JSON_ERROR_SYNTAX' ) && JSON_ERROR_SYNTAX === $last_error_code:
return 'Syntax error';

case defined( 'JSON_ERROR_UTF8' ) && JSON_ERROR_UTF8 === $last_error_code:
return 'Malformed UTF-8 characters, possibly incorrectly encoded';

case defined( 'JSON_ERROR_RECURSION' ) && JSON_ERROR_RECURSION === $last_error_code:
return 'Recursion detected';

case defined( 'JSON_ERROR_INF_OR_NAN' ) && JSON_ERROR_INF_OR_NAN === $last_error_code:
return 'Inf and NaN cannot be JSON encoded';

case defined( 'JSON_ERROR_UNSUPPORTED_TYPE' ) && JSON_ERROR_UNSUPPORTED_TYPE === $last_error_code:
return 'Type is not supported';

default:
return 'An unknown error occurred';
}
}
endif;

0 comments on commit 04ce8e3

Please sign in to comment.