<?php declare(strict_types=1);
namespace Sq\GraphQL\EventSubscriber;
use Sq\GraphQL\Exception\SqGraphQLException;
use Sq\Service\Environment;
use Sq\Service\Log\ExceptionLogger;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
class GraphQLExceptionSubscriber implements EventSubscriberInterface
{
public function __construct(
protected Environment $environment,
protected ExceptionLogger $exceptionLogger,
) {
}
/** @inheritDoc */
public static function getSubscribedEvents(): array
{
return [
KernelEvents::EXCEPTION => ['onException'],
];
}
public function onException(ExceptionEvent $event): void
{
$throwable = $event->getThrowable();
is_graphql_request($event->getRequest()) && $event->setResponse(static::createInternalServerErrorGraphQLResponse($this->environment->isDebug(), $throwable));
if ($throwable instanceof NotFoundHttpException || $throwable instanceof ResourceNotFoundException)
{
return;
}
$this->exceptionLogger->logInternalServerError($event->getThrowable());
}
public static function createInternalServerErrorGraphQLResponse($debug = false, ?\Throwable $e = null): Response
{
$error = new \GraphQL\Error\Error("INTERNAL_SERVER_ERROR");
$res = new \GraphQL\Executor\ExecutionResult(null, [$error]);
$resArray = $res->toArray();
if ($e instanceof SqGraphQLException)
{
$resArray['errors'][0]['extensions']['gql_message'] = $e->getMessage();
}
if ($debug && $e)
{
if ($e->getPrevious())
{
$previous = $e->getPrevious();
$resArray['errors'][0]['debug_previous'] = [
'message' => $previous->getMessage(),
'code' => $previous->getCode(),
'line' => $previous->getLine(),
'file' => $previous->getFile(),
];
}
$resArray['errors'][0]['debug_message'] = $e->getMessage();
$resArray['errors'][0]['debug_file'] = $e->getFile();
$resArray['errors'][0]['debug_line'] = $e->getLine();
$resArray['errors'][0]['debug_trace'] = $e->getTraceAsString();
}
return new JsonResponse($resArray, 500);
}
}