让所有未定义的路由在symfony 4中返回404

时间:2019-10-14 16:37:30

标签: symfony routing

我是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,而没有回溯?

我也在API控制器中抛出BadRequestHttpException,该异常也被转储到页面上。是否可以通过相同的方法解决?

1 个答案:

答案 0 :(得分:1)

正如许多人指出的那样,错误页面仅针对devtest环境生成。在您应在实时系统上使用的prod环境中,将显示一个通用的404页面,您可以对其进行自定义。

负责显示开发中的详细错误页面或生产中的常规404页面的系统是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和“常规”站点,则它不应干扰默认错误处理。