触发错误404.json.twig

时间:2016-01-27 03:02:22

标签: json rest symfony

我试图让我的自定义json错误模板由Symfony返回,但它不断返回HTML版本。使用休息客户端我已将 接受 内容类型 设置为" application / json&#34 ;但只返回error404.html.twig的内容,而不是error404.json.twig文件。

目前我通过一个完全无效的URL(即没有路由)对此进行测试,但是一旦我开始工作,我也会将其用于有效的URL,这些URL不会导致资源,并且内部代码会抛出一个HttpNotFoundException

1 个答案:

答案 0 :(得分:4)

在您的请求上设置标题实际上不会对返回的错误模板产生任何影响,尽管看起来这可能是逻辑路径。生成的错误模板基于请求格式,该格式可以在_format参数中设置,也可以在Request对象本身上手动设置。 this post中有一个解决方案,但是如果您收到404错误,则无法从没有路由的Controller中设置_format参数或$request->setRequestFormat('json')调用。

Symfony拥有非常好的文档how to customize error pages,包括您可能想要采用的路径,overriding the default ExceptionController。基本上,您会覆盖showAction()findTemplate()方法,该方法需要Accept标头并检查application/json。您还可以检查Content-Type标头作为附加要求。所以这里是你的听众的声明:

# app/config/services.yml
services:
    app.exception_controller:
    class: AppBundle\Controller\CustomExceptionController
    arguments: ['@twig', '%kernel.debug%']

然后设置Twig参数:

# app/config/config.yml
twig:
    exception_controller:  app.exception_controller:showAction

现在定义您的课程并覆盖您需要的相关部分。第一个示例通过检查showAction()标头然后修改Accept格式来覆盖Request

namespace AppBundle\Controller;

use Symfony\Bundle\TwigBundle\Controller\ExceptionController;

class CustomExceptionController extends ExceptionController
{
    /*
     * {@inheritDoc}
     */
    public function showAction(Request $request, FlattenException $exception, DebugLoggerInterface $logger = null)
    {
        if (in_array('application/json', $request->getAcceptableContentTypes())) {
            $request->setRequestFormat('json');
        }

        parent::showAction($request, $exception, $logger);
    }
}

Symfony说findTemplate()方法是找到要使用的模板的方法,所以你可以把代码放在那里。以下是覆盖该函数的示例,如果您需要满足两个条件,则需要额外检查Content-Type标题:

namespace AppBundle\Controller;

use Symfony\Bundle\TwigBundle\Controller\ExceptionController;

class CustomExceptionController extends ExceptionController
{
    /*
     * {@inheritDoc}
     */
    protected function findTemplate(Request $request, $format, $code, $showException)
    {
        if (in_array('application/json', $request->getAcceptableContentTypes()) &&
            0 === strpos($request->headers->get('Content-Type'), 'application/json')
        ) {
            $format = 'json';
        }

        parent::findTemplate($request, $format, $code, $showException);
    }
}

当然,您也可以working with the kernel.exception event自己创建一个异常监听器,以便进一步控制。

如果您使用FOSRestBundle,它会使用Request Accept标头和格式优先级配置通过侦听器尝试determine the request format for you。如果您使用此捆绑包,您可能可以避免自定义编码,只需依靠它。