簡體   English   中英

如何在 symfony5 中將所有 HttpExceptions 格式化為 json?

[英]How to format all HttpExceptions as json in symfony5?

在 symfony5 controller 中,我可以通過以下方式返回 json 響應:

 return $this->json(['key' => 'content');

然而,當我拋出 HttpException 時,我在開發和生產中都看到了默認的 html 錯誤頁面。

我想創建一個寧靜的api,所以我想將所有HttpExceptions轉換為json。

我想配置我的所有控制器以將它們的響應格式化為 json。 最多,我想添加一個異常處理程序,將異常轉換為正確的消息。 (在 prod 中它應該有更少的信息,在 dev 中它可能包含異常堆棧跟蹤。)

我怎樣才能做到這一點? 我以為我可以使用@Route注釋的format選項,但它不起作用。

這是我的示例 controller:

<?php declare(strict_types=1);

namespace App\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Annotation\Route;

class StatusController extends AbstractController
{
    /**
     * @Route("/status", name="status", format="json")
     * @Template
     * @return JsonResponse
     */
    public function status()
    {
        if (true) {
            // this will render as html, how to serialize it as json?
            throw new NotFoundHttpException("This is an example");
        }


        $ok = new \stdClass();
        $ok->status = "OK";

        return $this->json($ok);
    }
}

在尋找這個時,我遇到了這個 PR ,它似乎實現了我想要做的事情,但我不確定我錯過了什么。

symfony 博客上,我發現 Yonel Ceruto 的回答如下

您將需要安裝/啟用序列化程序組件,

但我不知道這意味着什么。


在開發和產品中,我得到了這些 html 視圖,而不是 json 響應:

產品

用於呈現異常的 html 的 prod 視圖

開發者

用於呈現異常的 html 視圖的開發視圖

原來我所缺少的只是安裝序列化程序包,正如symfony 文檔中指出的那樣:

composer require symfony/serializer-pack

之后,我的異常呈現為 json 很好。

package symfony/serializer-pack在我的環境中不起作用。

最后,我創建了一個ErrorController來響應 json。

namespace App\Controller;

use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Throwable;

class JsonErrorController
{
    public function show(Throwable $exception, LoggerInterface $logger)
    {
        return new JsonResponse($exception->getMessage(), $exception->getCode());
    }
}

創建一個事件監聽ExceptionListener並在services.yml中注冊

services:
    ...
    App\EventListener\ExceptionListener:
        tags:
            - { name: kernel.event_listener, event: kernel.exception }

ExceptionLister.php

// src/EventListener/ExceptionListener.php
namespace App\EventListener;

use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;

class ExceptionListener
{
    public function onKernelException(ExceptionEvent $event)
    {
        // You get the exception object from the received event
        $exception = $event->getThrowable();
        // Get incomming request
        $request   = $event->getRequest();

        // Check if it is a rest api request
        if ('application/json' === $request->headers->get('Content-Type'))
        {

            // Customize your response object to display the exception details
            $response = new JsonResponse([
                'message'       => $exception->getMessage(),
                'code'          => $exception->getCode(),
                'traces'        => $exception->getTrace()
            ]);

            // HttpExceptionInterface is a special type of exception that
            // holds status code and header details
            if ($exception instanceof HttpExceptionInterface) {
                $response->setStatusCode($exception->getStatusCode());
                $response->headers->replace($exception->getHeaders());
            } else {
                $response->setStatusCode(Response::HTTP_INTERNAL_SERVER_ERROR);
            }

            // sends the modified response object to the event
            $event->setResponse($response);
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM