如何使用Symfony 2和FOSRestBundle从同一路径提供HTML和JSON请求,除了_format之外还使用标头?

时间:2014-07-13 16:25:29

标签: php symfony fosrestbundle content-negotiation

我正在尝试使用Symfony和{{3}同时提供htmljson格式的内容(我也想最终允许xml) (版本1.3)。我成功地使用_format参数为路由提供了不同的内容,例如:

  • /foo.json将导致JSON响应,
  • /foo会产生HTML回复。

有没有办法使用_format以外的其他内容协调(在同一主机上!)相同的内容协商,例如Content-TypeAccept标题?

我看过FOSRestBundle,但我认为我对如何配置它有一个基本的误解。


给定定义的路线:

<route id="foo" pattern="/foo.{_format}" methods="GET">
    <default key="_controller">FooBundle:Foo:get</default>
    <default key="_format">html</default>
</route>

...执行以下操作:

public function getAction(Request $request)
{
    $view = View::create()
        ->setData(array('greeting' => 'hello world'))
        ->setFormat($request->getRequestFormat('html'))
        ->setTemplate('FooBundle:Foo:get.html.twig');
    return $this->get('fos_rest.view_handler')->handle($view);
}

...以及以下FOSRestBundle配置(代码段):

fos_rest:
  ...
  format_listener: true

如果我想要的协商内容采用非默认格式(_format),我需要在请求中指定html参数,如上所述。

但是,如果我为格式侦听器指定以下规则:

fos_rest:
  format_listener:
    rules:
      - { path: '^/', priorities: ['json'], fallback_format: ~, prefer_extension: false }
      - { path: '^/', priorities: ['html', '*/*'], fallback_format: html, prefer_extension: true }

浏览器请求将我的回复返回为Content-Type: application/json,但实际内容是text/html内容,而不是序列化的JSON。如果我在Accept请求中明确指定Accept: text/html标头,则我收到的响应的内容类型标头为Content-Type: text/html

非常感谢任何帮助!

1 个答案:

答案 0 :(得分:1)

如果您想要基于Content-type标头的内容协商,则需要使用BodyListener而不是FormatListener。 阅读documentation