« Documentation table of contents
Use of provided
ExceptionHandler
helper requires additional, manual installation steps to be made, otherwise Laravel's built-in handler will be used instead. See the details documented below.
Properly designed REST API should never hit consumer with anything but JSON. While it looks like
easy task, there's always chance for unexpected issue to occur. So we need to expect unexpected and
be prepared when it hit the fan. This means not only things like uncaught exception but also
Laravel's maintenance mode can pollute returned API responses which is unfortunately pretty common
among badly written APIs. Do not be one of them, and take care of that in advance with couple of
easy steps. In Laravel, unexpected situations are routed to Exception Handler. Unfortunately default
implementation is not JSON API friendly, therefore ResponseBuilder
provides drop-in replacement
for Laravel's handler. Once installed, it ensures only JSON response will be returned no matter what
happens.
If you are intent to use Exception Handler helper, you MUST configure it first in your config file (esp.
default
handler configuration)!
To make it works, edit app/Exceptions/Handler.php
file, and add
use MarcinOrlowski\ResponseBuilder\ExceptionHandlerHelper;
Next, register our handler in register()
method:
public function register()
{
$this->renderable(function (Throwable $ex, $request) {
return ExceptionHandlerHelper::render($request ,$ex );
});
}
From now on, in case of any troubles, regular and standardized JSON responses will be returned by your API instead of HTML error page.
ExceptionHandlerHelper
can be used out of the box as it requires no extra configuration, however
it's strongly recommended you at least assign your own api codes for the events it handles,
so you will know what module in your code thrown the exception. For consistency, I recommend
doing so even if you have just one module and do not chain APIs.
First edit your ApiCodes
class (that one which stores your API return code constants) and
define codes within your allowed code range (constants can be named as you like), representing
cases ExceptionHandlerHelper
handles:
public const HTTP_NOT_FOUND = ...;
public const HTTP_SERVICE_UNAVAILABLE = ...;
public const HTTP_EXCEPTION = ...;
public const UNCAUGHT_EXCEPTION = ...;
public const AUTHENTICATION_EXCEPTION = ...;
public const VALIDATION_EXCEPTION = ...;
then edit config/response_builder.php
file to map exceptions to your codes:
'exception_handler' => [
'exception' => [
'http_not_found' => ['code' => ApiCode::HTTP_NOT_FOUND],
'http_service_unavailable' => ['code' => ApiCode::HTTP_SERVICE_UNAVAILABLE],
'http_exception' => ['code' => ApiCode::HTTP_EXCEPTION],
'uncaught_exception' => ['code' => ApiCode::UNCAUGHT_EXCEPTION],
'authentication_exception' => ['code' => ApiCode::AUTHENTICATION_EXCEPTION],
'validation_exception' => ['code' => ApiCode::VALIDATION_EXCEPTION],
],
],
You can also configure HTTP return code to use with each exception, by using http_code
key
for each of exceptions you need.
You must use valid HTTP error code. Codes outside of range from
400
(BaseApiCodes::ERROR_HTTP_CODE_MIN
) to599
(BaseApiCodes::ERROR_HTTP_CODE_MAX
) will be ignored and default value will be used instead.
I.e. to alter HTTP code for http_not_found
:
'http_not_found' => [
'code' => BaseApiCodes::EX_HTTP_NOT_FOUND(),
'http_code' => HttpResponse::HTTP_BAD_REQUEST,
],
See default config vendor/marcin-orlowski/laravel-api-response-builder/config/response_builder.php
file for all entries you can modify.
Both keys code
and http_code
are optional and can be used selectively according to your needs.
Helper will fall back to defaults if these are not found:
'http_not_found' => [
'http_code' => HttpResponse::HTTP_BAD_REQUEST,
],
'http_service_unavailable' => [
'code' => BaseApiCodes::EX_HTTP_SERVICE_UNAVAILABLE(),
],
'uncaught_exception' => [
],
Helper will try to use exception's status code if no dedicated http_code
value is provided but it
will fall to default HttpResponse::HTTP_BAD_REQUEST
code
(HttpResponse::HTTP_INTERNAL_SERVER_ERROR
for uncaught exceptions) if exceptions status code is
0
(zero).
If you want to override built-in messages for any (or all) exceptions, edit
config/response_builder.php
and add appropriate entry to map
array:
'map' => [
BaseApiCodes::EX_HTTP_NOT_FOUND() => 'api.http_not_found',
BaseApiCodes::EX_HTTP_SERVICE_UNAVAILABLE() => 'api.http_service_unavailable',
BaseApiCodes::EX_HTTP_EXCEPTION() => 'api.http_exception',
BaseApiCodes::EX_UNCAUGHT_EXCEPTION() => 'api.uncaught_exception',
BaseApiCodes::EX_AUTHENTICATION_EXCEPTION() => 'api.authentication_exception',
BaseApiCodes::EX_VALIDATION_EXCEPTION() => 'api.validation_exception',
...
],
where api.xxxx
entry must be valid localization string key from your app's localization strings
pool as per Lang's requirements. You can use placeholders in your messages. Supported are
:api_code
being substituted by actual code assigned to this exception and :message
replaced by exception's getMessage()
return value.
Please note that some 3rd party packages may also provide own exception handling helpers and may
recommend using said handlers in your application. Unfortunately this will cause conflict with
ResponseBuilder
's handler which usually lead to one (or another) handler not being executed
at all.
For example if your API delegates OAuth2 related tasks to popular
lucadegasperi/oauth2-server-laravel
package, then you
must NOT use its OAuthExceptionHandlerMiddleware
class and ensure it is not set, by inspecting
app/Kernel.php
file
and ensuring the following line (if present) is removed or commented out:
// remove or comment out
'LucaDegasperi\OAuth2Server\Middleware\OAuthExceptionHandlerMiddleware',
The above assumes you keep your codes in ApiCodes
class stored in app/ApiCodes.php
and using
App\
namespace.