Files
SomniaRooms/src/EventSubscriber/ApiExceptionSubscriber.php
T
Daniel-Garmig 37462e4646
CI / Docker Lint (push) Successful in 21s
Added Validation to API requests.
- Added Symfony Validation Lib.
- Updated API DTOs to include validation constraints.
2024-10-18 20:32:36 +02:00

87 lines
3.2 KiB
PHP

<?php
namespace App\EventSubscriber;
use App\ApiErrorException;
use App\DTO\ApiErrorMessage;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Symfony\Component\Validator\Exception\ValidationFailedException;
class ApiExceptionSubscriber implements EventSubscriberInterface
{
public function __construct(
private LoggerInterface $logger,
) {}
public function onKernelException(ExceptionEvent $event): void
{
$e = $event->getThrowable();
if ($e instanceof ApiErrorException) {
$apiErrorMsg = $e->getApiErrorMsg();
} else {
$statusCode = $e instanceof HttpExceptionInterface ? $e->getStatusCode() : 500;
$apiErrorMsg = new ApiErrorMessage($statusCode);
/*
* If it's an HttpException message (e.g. for 404, 403),
* we'll say as a rule that the exception message is safe
* for the client. Otherwise, it could be some sensitive
* low-level exception, which should *not* be exposed
*/
if ($e instanceof HttpExceptionInterface) {
//Check if it's a Validation error.
// When using MapRequestPayload() ValidationErrors throw HttpExceptions.
$prev = $e->getPrevious();
if ($prev instanceof ValidationFailedException) {
//Get validation error details.
$errorList = [];
$violationList = $prev->getViolations();
foreach ($violationList as $violation) {
$errorList[] = [
'field' => $violation->getPropertyPath(),
'message' => $violation->getMessage(),
];
}
$apiErrorMsg->setExtraData('detail', "Validation Error. See errorList for details");
$apiErrorMsg->setExtraData('errorList', $errorList);
} else {
//Get exception error message.
$apiErrorMsg->setExtraData('detail', $e->getMessage());
}
}
}
//Send error to logs.
$exceptionError = [
'message' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'trace' => $e->getTrace()
];
$errorContext = array_merge($apiErrorMsg->toArray(), $exceptionError);
$this->logger->error("API ERROR Exception:", $errorContext);
//Send error to client.
$response = new JsonResponse(
$apiErrorMsg->toArray(),
$apiErrorMsg->getStatusCode()
);
$response->headers->set('Content-Type', 'application/problem+json');
$event->setResponse($response);
}
public static function getSubscribedEvents(): array
{
return [
KernelEvents::EXCEPTION => 'onKernelException',
];
}
}