Revision: Thu, 28 May 2020 13:49:47 GMT

HTTP - Error Pages

Your application will expose some errors and exceptions, some of which must be delivered to the client, and some of them don't.

The HTTP component includes the default error handling middleware, which used to intercept and log critical errors and user-level exceptions.

To enable such middleware add the Spiral\Bootloader\Http\ErrorHandlerBootloader to your application:

namespace App;

use Spiral\Bootloader as Framework;
use Spiral\DotEnv\Bootloader as DotEnv;
use Spiral\Framework\Kernel;
use Spiral\Prototype\Bootloader as Prototype;
use Spiral\Scaffolder\Bootloader\ScaffolderBootloader;

class App extends Kernel
{
    /*
     * List of components and extensions to be automatically registered
     * within system container on application start.
     */
    protected const LOAD = [
        // ...

        Framework\Http\HttpBootloader::class,
        Framework\Http\RouterBootloader::class,
        Framework\Http\ErrorHandlerBootloader::class,

        // ...
    ];
}

Application Exceptions

The middleware will handle application exceptions and will render them in a developer-friendly mode. To suppress the delivery of the exception details to the browser, set the env variable DEBUG to false. In this case, the default 500 error page will be displayed.

Do not deploy your application to production with enabled debug mode.

Client Exceptions

There are several exceptions you can throw from your controllers and middleware to cause HTTP level error page, for example we can trigger 404 Not Found using NotFoundException:

namespace App\Controller;

use Spiral\Core\Container\SingletonInterface;
use Spiral\Http\Exception\ClientException\NotFoundException;

class HomeController implements SingletonInterface
{
    public function index()
    {
        throw new NotFoundException();
    }
}

Other exceptions include:

Code Exception
400 Spiral\Http\Exception\ClientException\BadRequestException
401 Spiral\Http\Exception\ClientException\UnauthorizedException
403 Spiral\Http\Exception\ClientException\ForbiddenException
404 Spiral\Http\Exception\ClientException\NotFoundException
500 Spiral\Http\Exception\ClientException\ServerErrorException

Do not use http exceptions inside your services and repositories as it will couple your implementation to http dispatcher. Use domain-specific exceptions and their mapping to http exception instead.

Page Renderer

By default, the middleware will use a simple error page without any styles attached. To implement your error page renderer implement and bind in container the Spiral\Http\ErrorHandler\RendererInterface interface:

namespace App\Errors;

use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Spiral\Http\ErrorHandler\RendererInterface;
use Spiral\Views\ViewsInterface;

class NiceRenderer implements RendererInterface
{
    private $responseFactory;

    private $views;

    public function __construct(
        ResponseFactoryInterface $responseFactory,
        ViewsInterface $views
    ) {
        $this->responseFactory = $responseFactory;
        $this->views = $views;
    }

    public function renderException(Request $request, int $code, string $message): Response
    {
        $response = $this->responseFactory->createResponse($code);

        $response->getBody()->write(
            $this->views->render('errors/' . (string)$code)
        );

        return $response->withStatus($code, $message);
    }
}

Bind it via bootloader:

namespace App\Bootloader;

use App\Errors\NiceRenderer;
use Spiral\Boot\Bootloader\Bootloader;
use Spiral\Bootloader\Http\ErrorHandlerBootloader;
use Spiral\Http\ErrorHandler\RendererInterface;

class NiceErrorsBootloader extends Bootloader
{
    public const DEPENDENCIES = [
        ErrorHandlerBootloader::class
    ];

    public const SINGLETONS = [
        RendererInterface::class => NiceRenderer::class
    ];
}

Logging

The default application includes Monolog handler, which, by default, subscribed to the messages sent by the ErrorHandlerMiddleware. The http error log is located in app/runtime/logs/http.log and configured in App\Bootloaders\LoggingBootloader:

namespace App\Bootloader;

use Spiral\Boot\Bootloader\Bootloader;
use Spiral\Http\Middleware\ErrorHandlerMiddleware;
use Spiral\Monolog\Bootloader\MonologBootloader;

class LoggingBootloader extends Bootloader
{
    /**
     * @param MonologBootloader $monolog
     */
    public function boot(MonologBootloader $monolog)
    {
        $monolog->addHandler(
            ErrorHandlerMiddleware::class,
            $monolog->logRotate(directory('runtime') . 'logs/http.log')
        );
    }
}
Edit this page