mirror of
https://github.com/flarum/framework.git
synced 2025-05-23 07:09:57 +08:00
Improve API error handling
- Change 'path' key to 'source.pointer', as per spec - Add 500 error detail if debug mode is on
This commit is contained in:
@ -129,7 +129,7 @@ export default class Modal extends Component {
|
|||||||
m.redraw();
|
m.redraw();
|
||||||
|
|
||||||
if (errors) {
|
if (errors) {
|
||||||
this.$('form [name=' + errors[0].path + ']').select();
|
this.$('form [name=' + errors[0].source.pointer.replace('/data/attributes/', '') + ']').select();
|
||||||
} else {
|
} else {
|
||||||
this.$('form :input:first').select();
|
this.$('form :input:first').select();
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,8 @@ namespace Flarum\Api;
|
|||||||
|
|
||||||
use Flarum\Core\Users\User;
|
use Flarum\Core\Users\User;
|
||||||
use Illuminate\Contracts\Container\Container;
|
use Illuminate\Contracts\Container\Container;
|
||||||
|
use Exception;
|
||||||
|
use Flarum\Api\Middleware\JsonApiErrors;
|
||||||
|
|
||||||
class Client
|
class Client
|
||||||
{
|
{
|
||||||
@ -41,7 +43,13 @@ class Client
|
|||||||
/** @var \Flarum\Api\Actions\Action $action */
|
/** @var \Flarum\Api\Actions\Action $action */
|
||||||
$action = $this->container->make($actionClass);
|
$action = $this->container->make($actionClass);
|
||||||
|
|
||||||
$response = $action->handle(new Request($input, $actor));
|
try {
|
||||||
|
$response = $action->handle(new Request($input, $actor));
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$middleware = new JsonApiErrors();
|
||||||
|
|
||||||
|
$response = $middleware->handle($e);
|
||||||
|
}
|
||||||
|
|
||||||
return new Response($response);
|
return new Response($response);
|
||||||
}
|
}
|
||||||
|
@ -17,45 +17,52 @@ use Psr\Http\Message\ResponseInterface as Response;
|
|||||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||||
use Zend\Diactoros\Response\JsonResponse;
|
use Zend\Diactoros\Response\JsonResponse;
|
||||||
use Zend\Stratigility\ErrorMiddlewareInterface;
|
use Zend\Stratigility\ErrorMiddlewareInterface;
|
||||||
|
use Flarum\Core;
|
||||||
|
use Exception;
|
||||||
|
|
||||||
class JsonApiErrors implements ErrorMiddlewareInterface
|
class JsonApiErrors implements ErrorMiddlewareInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
public function __invoke($error, Request $request, Response $response, callable $out = null)
|
public function __invoke($e, Request $request, Response $response, callable $out = null)
|
||||||
{
|
{
|
||||||
if ($error instanceof JsonApiSerializable) {
|
return $this->handle($e);
|
||||||
$status = $error->getStatusCode();
|
}
|
||||||
|
|
||||||
$errors = $error->getErrors();
|
public function handle(Exception $e)
|
||||||
} else if ($error instanceof ValidationException) {
|
{
|
||||||
|
if ($e instanceof JsonApiSerializable) {
|
||||||
|
$status = $e->getStatusCode();
|
||||||
|
|
||||||
|
$errors = $e->getErrors();
|
||||||
|
} else if ($e instanceof ValidationException) {
|
||||||
$status = 422;
|
$status = 422;
|
||||||
|
|
||||||
$errors = $error->errors()->toArray();
|
$errors = $e->errors()->toArray();
|
||||||
$errors = array_map(function ($field, $messages) {
|
$errors = array_map(function ($field, $messages) {
|
||||||
return [
|
return [
|
||||||
'detail' => implode("\n", $messages),
|
'detail' => implode("\n", $messages),
|
||||||
'path' => $field,
|
'source' => ['pointer' => '/data/attributes/' . $field],
|
||||||
];
|
];
|
||||||
}, array_keys($errors), $errors);
|
}, array_keys($errors), $errors);
|
||||||
} else if ($error instanceof ModelNotFoundException) {
|
} else if ($e instanceof ModelNotFoundException) {
|
||||||
$status = 404;
|
$status = 404;
|
||||||
|
|
||||||
$errors = [];
|
$errors = [];
|
||||||
} else {
|
} else {
|
||||||
$status = 500;
|
$status = 500;
|
||||||
|
|
||||||
// If it seems to be a valid HTTP status code, we pass on the
|
$error = [
|
||||||
// exception's status.
|
'code' => $status,
|
||||||
$errorCode = $error->getCode();
|
'title' => 'Internal Server Error'
|
||||||
if (is_int($errorCode) && $errorCode >= 400 && $errorCode < 600) {
|
];
|
||||||
$status = $errorCode;
|
|
||||||
|
if (Core::inDebugMode()) {
|
||||||
|
$error['detail'] = (string) $e;
|
||||||
}
|
}
|
||||||
|
|
||||||
$errors = [
|
$errors = [$error];
|
||||||
['title' => $error->getMessage()]
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// JSON API errors must be collected in an array under the
|
// JSON API errors must be collected in an array under the
|
||||||
|
@ -12,6 +12,21 @@ namespace Flarum\Core\Exceptions;
|
|||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
|
||||||
class InvalidConfirmationTokenException extends Exception
|
class InvalidConfirmationTokenException extends Exception implements JsonApiSerializable
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getStatusCode()
|
||||||
|
{
|
||||||
|
return 403;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getErrors()
|
||||||
|
{
|
||||||
|
return ['code' => 'invalid_confirmation_token'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,9 +27,7 @@ class ValidationException extends Exception implements JsonApiSerializable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the HTTP status code to be used for this exception.
|
* {@inheritdoc}
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
*/
|
||||||
public function getStatusCode()
|
public function getStatusCode()
|
||||||
{
|
{
|
||||||
@ -37,15 +35,14 @@ class ValidationException extends Exception implements JsonApiSerializable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an array of errors, formatted as JSON-API error objects.
|
* {@inheritdoc}
|
||||||
*
|
|
||||||
* @see http://jsonapi.org/format/#error-objects
|
|
||||||
* @return array
|
|
||||||
*/
|
*/
|
||||||
public function getErrors()
|
public function getErrors()
|
||||||
{
|
{
|
||||||
return array_map(function ($path, $detail) {
|
return array_map(function ($path, $detail) {
|
||||||
return compact('path', 'detail');
|
$source = ['pointer' => '/data/attributes/' . $path];
|
||||||
|
|
||||||
|
return compact('source', 'detail');
|
||||||
}, array_keys($this->messages), $this->messages);
|
}, array_keys($this->messages), $this->messages);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user