我是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
,该异常也被转储到页面上。是否可以通过相同的方法解决?
答案 0 :(得分:1)
正如许多人指出的那样,错误页面仅针对dev
和test
环境生成。在您应在实时系统上使用的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和“常规”站点,则它不应干扰默认错误处理。