Все неопределенные маршруты возвращают 404 в symfony 4 - PullRequest
1 голос
/ 14 октября 2019

Я новичок в Symfony и работаю над первым проектом, использующим Symfony 4.1. У меня есть домашняя страница, настроенная в '/', и это работает. Цель этого проекта - создать REST API, и у меня есть маршрут, определенный на /api/argument/, и это тоже работает нормально.

Однако, когда я перехожу к /api или любому другому маршруту с чем-то в пути (например, /car, /apple, /something/else), я получаю 404 в ответе HTTP, нона странице отображается обратная трассировка исключения.

Sorry, the page you are looking for could not be found.

NotFoundHttpException

No route found for "GET /oijoij"
in RouterListener.php line 139
at RouterListener->onKernelRequest(object(GetResponseEvent), 'kernel.request', object(EventDispatcher))in EventDispatcher.php line 212
...

Итак, в .env я установил

APP_ENV=test
APP_DEBUG=0

И теперь, вместо довольно отпечатанного HTML-кода, я получаю просто текстовое сообщение об ошибке

Fatal error: Uncaught Symfony\Component\Routing\Exception\ResourceNotFoundException in www\project\var\cache\test\srcTestProjectContainerUrlMatcher.php:50 Stack trace: ...

Как мне настроить так, чтобы неопределенные маршруты возвращали 404 со страницей шаблона 404, без обратной трассировки?

Я также добавляю BadRequestHttpException в мои контроллеры API, и это исключение просто сбрасывается и на страницу. Это решается тем же методом?

1 Ответ

1 голос
/ 15 октября 2019

Как отмечают многие, страницы ошибок генерируются только для среды dev и test. В среде prod, которую вы должны использовать в своей действующей системе, отобразится общая страница 404, которую вы можете настроить.

Система, отвечающая за отображение подробной страницы ошибки в процессе разработки или обычной 404page in production - это цикл событий Symfony, точнее, событие kernel.exception, которое прослушивается, а затем любые неперехваченные ошибки и исключения будут преобразованы в ответ страницы с ошибкой. Поскольку вы пишете API, возможно, вы захотите зарегистрировать свой собственный слушатель и вернуть ответ JSON вместо обычного HTML.

Подписчик события для этого может выглядеть примерно так:

<?php declare(strict_types = 1);

namespace App\Api\Response;

use Exception;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\HttpKernel\KernelEvents;

final class ExceptionToJsonResponseSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        return [
            KernelEvents::EXCEPTION => 'onKernelException',
        ];
    }

    public function onKernelException(GetResponseForExceptionEvent $event): void
    {
        // Skip if request is not an API-request
        $request = $event->getRequest();
        if (strpos($request->getPathInfo(), '/api') !== 0) {
            return;
        }

        $exception = $event->getException();
        $error = [
            'type' => $this->getErrorTypeFromException($exception),
            // Warning! Passing the exception message without checks is insecure.
            // This will potentially leak sensitive information.
            // Do not use this in production!
            'message' => $exception->getMessage(),
        ];
        $response = new JsonResponse($error, $this->getStatusCodeFromException($exception));

        $event->setResponse($response);
    }

    private function getStatusCodeFromException(Exception $exception): int
    {
        if ($exception instanceof HttpException) {
            return $exception->getStatusCode();
        }

        return 500;
    }

    private function getErrorTypeFromException(Exception $exception): string
    {
        $parts = explode('\\', get_class($exception));

        return end($parts);
    }
}

Это преобразует любое исключение в JSON-ответ с пользовательским форматом, подобным следующему:

{
    "type": "NotFoundException",
    "message": "Could not find argument with id x"
}

Этот слушатель будет делать это только для маршрутов, начинающихся с /api, поэтому, если у вас есть и API, и«Обычный» сайт не должен мешать обработке ошибок по умолчанию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...