Files
project-manager/src/Http/JsonErrorHandler.php
T

77 lines
2.3 KiB
PHP
Raw Normal View History

2026-09-03 17:35:10 +01:00
<?php
declare(strict_types=1);
namespace App\Http;
use App\Exception\ApiException;
use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Exception\HttpMethodNotAllowedException;
use Slim\Exception\HttpNotFoundException;
use Throwable;
/**
* Renders every uncaught error as a consistent JSON envelope:
*
* { "error": { "message": string, "details"?: object } }
*/
final class JsonErrorHandler
{
public function __construct(
private readonly ResponseFactoryInterface $responseFactory,
private readonly bool $displayErrorDetails,
) {
}
public function __invoke(
Request $request,
Throwable $exception,
bool $displayErrorDetails,
bool $logErrors,
bool $logErrorDetails,
): Response {
[$status, $payload] = $this->describe($exception);
$response = $this->responseFactory->createResponse($status);
$response->getBody()->write(
(string) json_encode($payload, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)
);
return $response->withHeader('Content-Type', 'application/json');
}
/**
* @return array{0: int, 1: array<string, mixed>}
*/
private function describe(Throwable $exception): array
{
if ($exception instanceof ApiException) {
$error = ['message' => $exception->getMessage()];
if ($exception->getDetails() !== []) {
$error['details'] = $exception->getDetails();
}
return [$exception->getStatusCode(), ['error' => $error]];
}
if ($exception instanceof HttpNotFoundException) {
return [404, ['error' => ['message' => 'The requested resource was not found.']]];
}
if ($exception instanceof HttpMethodNotAllowedException) {
return [405, ['error' => ['message' => 'Method not allowed for this resource.']]];
}
$error = ['message' => 'An unexpected error occurred.'];
if ($this->displayErrorDetails) {
$error['message'] = $exception->getMessage();
$error['exception'] = $exception::class;
$error['file'] = $exception->getFile() . ':' . $exception->getLine();
}
return [500, ['error' => $error]];
}
}