Error handler based on route

Hello.

I’ve setup an Error Middleware in middlewares.php:

$errorMiddleware = $app->addErrorMiddleware(true, true, true);
$errorMiddleware->setDefaultErrorHandler($container->get(DefaultErrorHandler::class));

with DefaultErrorHandler copied from https://github.com/odan/slim4-skeleton/blob/master/src/Handler/DefaultErrorHandler.php

And it works and return html errors.

But for some routes (api routes), I’d like to have json errors, something like:

$errorMiddleware = $app->addErrorMiddleware(true, true, true);
$errorHandler = $errorMiddleware->getDefaultErrorHandler();
$errorHandler->forceContentType('application/json);

But I do not find how to setup that in my routes:

$app->group('/api', function (Group $groupApi) {
    $groupApi->get('/dogs', DogApiController::class. ':getDogs')->setName('api-dogs');
 })->add(ApiErrorMiddleware::class);

I’ve tried that:

class ApiErrorMiddleware implements Middleware
{

    private $logger;
    private $app;

    public function __construct(Logger $logger, App $app)
    {
        $this->logger = $logger;
        $this->app = $app;
    }

    public function process(Request $request, RequestHandler $handler): Response
    {
        $this->logger->debug("...");

        $errorMiddleware = $this->app->addErrorMiddleware(true, true, true);
        $errorHandler = $errorMiddleware->getDefaultErrorHandler();
        $errorHandler->forceContentType('application/json');

        return $handler->handle($request);
    }
}

But it has no effect :frowning:

is there a way to replace the handler from a middleware ?

Note that this middleware is optional, so you do not need to use the Slim error handler at all. If you have some special requirements, then you may also add your own ErrorHandler middleware that does content negotiation on it’s own, see here.

If you still want to use the Slim error handler middleware with the integrated content negotiation, you could register a error render for each content-type using the registerErrorRenderer method. Example:

// Add Error Middleware
$errorMiddleware = $app->addErrorMiddleware(true, true, true);

// Get the default error handler and register custom error renderers
$errorHandler = $errorMiddleware->getDefaultErrorHandler();
$errorHandler->registerErrorRenderer('text/html', HtmlErrorRenderer::class);
$errorHandler->registerErrorRenderer('application/json', JsonErrorRenderer::class);
// ...

$app->run();

For any content type you can register your own error renderer. So first define a new error renderer that implements \Slim\Interfaces\ErrorRendererInterface.

<?php

use App\Middleware;

use Slim\Interfaces\ErrorRendererInterface;
use Throwable;

final class HtmlErrorRenderer implements ErrorRendererInterface
{
    public function __invoke(Throwable $exception, bool $displayErrorDetails): string
    {
        return 'My HTML output';
    }
}

Read more: Error Middleware - Slim Framework