Symfony请求对象具有错误的属性(尤其是`$ request-> header-> get(' accept')`)

时间:2014-11-18 07:53:33

标签: symfony http-headers xmlhttprequest

在我的控制器功能中,我需要根据接受的内容类型以及请求的方式返回不同的回复。但由于某些原因,$request->header->get( 'accept' )$request->getRequestFormat()总是返回HTML(或分别为" text / html")虽然浏览器根据Firebug发送了不同的内容,但Wireshark也确认了原始请求真的不一样。

基本上我的代码如下所示:

public function someControllerAction() {
  $request = $this->getRequest();

  if( $request->isXmlHttpRequest() && $request->getRequestFormat() == 'html' ) {
    // (1) Return some HTML fragment that is used to update the DOM at client side
  } else if( $request->isXmlHttpRequest() && $request->getRequestFormat() == 'json' ) {
    // (2) Return a JSON object
  } else if( $request->getRequestFormat() == 'html' ) {
    // (3) Return a full HTML page from a TWIG template
  }

  // In all other cases, return a 406 error
}

由于某种原因,只执行case(1)或case(3),因为请求的格式总是等于HTML。我已经尝试了

die( var_dump( $request->header ) )

看看Symfony认为标题是什么,我注意到标题中的一些其他细微变化与Wireshark所说的相比。例如,所有内容都转换为小写。

目前,我最好的猜测是,在Symfony核心深处的某个地方似乎会发生某种规范化,它也会用默认的" text / html"替换Accept-Header-Field。有趣的是,X-Requested-With-Field没有标准化,但幸存下来。

我需要更改请求对象返回实际(真实)标题字段吗?

更新:

的结果
die( var_dump( getallheaders() ) );

也显示错误的标题。 Symfony是否操作本机PHP变量,或者这是否表明Apache在将其传递给PHP处理程序之前会使用accept标头?

2 个答案:

答案 0 :(得分:1)

我终于找到了问题所在。首先,正如在另一个答案中已经提到的那样,$request->getRequestFormat()是另一回事。 (它很难连接到占位符_format。)但它不是$request-getContentType(),也不是评论中讨论的。 HTTP-Accept-Header既可以通过$request->headers->get('accept')获得,也可以通过$request-> getAcceptableContentTypes()以更易于使用的方式获得。但这只是解决方案的一部分,因为$request->getAcceptableContentTypes()仍然会返回一个错误值的数组。

最终解决方案是$request绝不能通过getRequest() BUT获取作为控制器方法的第一个参数。正如我在Upgrade Guide to Symfony 3中找到的那样 {2.4}已弃用getRequest()。似乎getRequest()返回的是与通过参数注入的对象不同的对象,并且在某些条件下,第一种方法不能可靠地保持Accept-Header不变。也许,人们可以称之为一个错误,但如果getRequest()被弃用,我也不会打扰。 (顺便说一句:为什么甚至官方的Symfony文档“The Book”和“The Cookbook”都提供了使用弃用方法的示例?!)。

无论如何,完全可行的解决方案是

use Symfony\Component\HttpFoundation\Request;

public function someControllerAction( Request $request ) {
  if( $request->isXmlHttpRequest() && in_array( 'text/html', $request->getAcceptableContentTypes() ) ) {
    // (1) Return some HTML fragment that is used to update the DOM at client side
  } else if( $request->isXmlHttpRequest() && in_array( 'application/json', $request->getAcceptableContentTypes() ) ) {
    // (2) Return a JSON object
  } else if( in_array( 'text/html', $request->getAcceptableContentTypes() ) ) {
    // (3) Return a full HTML page from a TWIG template
  }

  // In all other cases, return a 406 error
}

答案 1 :(得分:0)

请注意$request->getRequestFormat()不进行实际的格式检查。它仅依赖于_format请求参数(see the doc)。您应该使用$request->getContentType()代替。