如何使用 Wordpress REST API 处理未捕获的异常?
How to handle uncaught exceptions with the Wordpress REST API?
假设我有一个自定义的 Wordpress REST API 路由并且我在回调中抛出了一个未处理的异常:
register_rest_route( $namespace, "/test", [
"methods" => "get",
"permission_callback" => "__return_true",
"callback" => function( $req ) {
throw new \Exception( "Error!!" );
}
]);
如果我查询路由,Wordpress return 会显示一个显示错误消息的 HTML 页面,这对于主题或管理区域来说很好,但对于 REST API我宁愿return一个WP_Error
.
我想我可以在回调代码周围放置一个 try/catch 块,如下所示:
register_rest_route( $namespace, "/test", [
"methods" => "get",
"permission_callback" => "__return_true",
"callback" => function( $req ) {
try {
throw new \Exception( "Error!!" );
} catch( \Throwable $e ) {
return new \WP_Error( "rest_error", $e->get_error_message() );
}
}
]);
但是我必须为我的所有自定义路线执行此操作,对吗?
有什么方法可以为任何自定义端点中抛出的未捕获异常设置“全局”默认响应?
我找到了一种方法 set_exception_handler
。不确定这是否是最好的方法,但它似乎有效:
set_exception_handler( array( $this, "handle_uncaught_exceptions" ) );
public function handle_uncaught_exceptions( \Throwable $e ) {
// First of all, log the exception
log_from_exception( "errors", "alert", $e );
// Now we have to return a response. By default, when an uncaught exception is thrown (fatal error) Wordpress returns
// an HTML page with an error message. That is fine eg. for a theme or the admin area, but for REST requests we'd rather
// return a response that looks like a \WP_REST_Response
if( is_rest_request() ) {
// Set the response code to 500
http_response_code(500);
// Set the cross-domain headers
header( "Access-Control-Allow-Origin: " . $_ENV["FRONTEND_URL"];
header( "Access-Control-Allow-Credentials: true" );
// Send the response
$response = [
"code" => "rest_fatal_error",
"message" => "A fatal error occurred"
];
wp_send_json( $response );
} else {
// For non-REST requests, we want to reset the default behavior, ie. sending an HTML page with an error message
wp_die( $e->getMessage() );
}
}
is_rest_request
是一个自定义函数:
function is_rest_request() {
$uri = $_SERVER["REQUEST_URI"];
if ( empty( $uri ) ) {
return false;
}
$restPrefix = trailingslashit( rest_get_url_prefix() ); // Resolves to "wp-json/"
$isRestApiRequest = strpos( $uri, $restPrefix ) !== false;
return $isRestApiRequest;
}
假设我有一个自定义的 Wordpress REST API 路由并且我在回调中抛出了一个未处理的异常:
register_rest_route( $namespace, "/test", [
"methods" => "get",
"permission_callback" => "__return_true",
"callback" => function( $req ) {
throw new \Exception( "Error!!" );
}
]);
如果我查询路由,Wordpress return 会显示一个显示错误消息的 HTML 页面,这对于主题或管理区域来说很好,但对于 REST API我宁愿return一个WP_Error
.
我想我可以在回调代码周围放置一个 try/catch 块,如下所示:
register_rest_route( $namespace, "/test", [
"methods" => "get",
"permission_callback" => "__return_true",
"callback" => function( $req ) {
try {
throw new \Exception( "Error!!" );
} catch( \Throwable $e ) {
return new \WP_Error( "rest_error", $e->get_error_message() );
}
}
]);
但是我必须为我的所有自定义路线执行此操作,对吗?
有什么方法可以为任何自定义端点中抛出的未捕获异常设置“全局”默认响应?
我找到了一种方法 set_exception_handler
。不确定这是否是最好的方法,但它似乎有效:
set_exception_handler( array( $this, "handle_uncaught_exceptions" ) );
public function handle_uncaught_exceptions( \Throwable $e ) {
// First of all, log the exception
log_from_exception( "errors", "alert", $e );
// Now we have to return a response. By default, when an uncaught exception is thrown (fatal error) Wordpress returns
// an HTML page with an error message. That is fine eg. for a theme or the admin area, but for REST requests we'd rather
// return a response that looks like a \WP_REST_Response
if( is_rest_request() ) {
// Set the response code to 500
http_response_code(500);
// Set the cross-domain headers
header( "Access-Control-Allow-Origin: " . $_ENV["FRONTEND_URL"];
header( "Access-Control-Allow-Credentials: true" );
// Send the response
$response = [
"code" => "rest_fatal_error",
"message" => "A fatal error occurred"
];
wp_send_json( $response );
} else {
// For non-REST requests, we want to reset the default behavior, ie. sending an HTML page with an error message
wp_die( $e->getMessage() );
}
}
is_rest_request
是一个自定义函数:
function is_rest_request() {
$uri = $_SERVER["REQUEST_URI"];
if ( empty( $uri ) ) {
return false;
}
$restPrefix = trailingslashit( rest_get_url_prefix() ); // Resolves to "wp-json/"
$isRestApiRequest = strpos( $uri, $restPrefix ) !== false;
return $isRestApiRequest;
}