<?php
namespace App\EventSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Symfony\Component\HttpKernel\KernelEvents;
/**
* Converts exceptions thrown inside /api/v1/* into the uniform JSON error envelope.
*/
class ApiExceptionSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
KernelEvents::EXCEPTION => ['onException', 0],
];
}
public function onException(ExceptionEvent $event): void
{
$request = $event->getRequest();
if (!str_starts_with($request->getPathInfo(), '/api/v1')) {
return;
}
$ex = $event->getThrowable();
if ($ex instanceof HttpExceptionInterface) {
$status = $ex->getStatusCode();
$code = match (true) {
$status === 404 => 'NOT_FOUND',
$status === 405 => 'METHOD_NOT_ALLOWED',
$status === 400 => 'BAD_REQUEST',
$status === 413 => 'FILE_TOO_LARGE',
$status === 415 => 'UNSUPPORTED_MEDIA_TYPE',
$status === 422 => 'VALIDATION_FAILED',
$status >= 500 => 'INTERNAL_ERROR',
default => 'ERROR',
};
$message = $ex->getMessage() ?: 'Er is iets misgegaan.';
} else {
$status = 500;
$code = 'INTERNAL_ERROR';
$message = 'Er is een interne fout opgetreden.';
}
$event->setResponse(new JsonResponse([
'error' => [
'code' => $code,
'message' => $message,
],
], $status));
}
}