symfony2中的$ request-> isXmlHttpRequest()是否可靠?

时间:2012-08-13 20:33:01

标签: ajax symfony

让我们考虑如下情况:

  1. 用户选择过滤器按钮,该按钮用于创建对symfony2控制器的AJAX调用,并以JSON格式返回结果。
  2. 用户选择其他一些链接,系统会将他重定向到页面
  3. 用户选择浏览器后退按钮。
  4. 用户将看到JSON响应,但他应该看到原始页面。
  5. 我的控制器如下所示:

    /**
     * 
     *
     * @Route("/ajax", name="ajax_route" , options={"expose"=true})
     * @Template()
     */
    public function someAction()
    {
        $request = $this->getRequest();
    
        $json = array( );
    
        if($request->isXmlHttpRequest())
        {
    
            $res = json_encode($json);
    
            return new Response($res , 200 , array( 'Content-Type' => 'application/json' ));
        }
    
        return array( );
    }  
    

    换句话说,如果用户按下后退按钮,if($request->isXmlHttpRequest())将返回true,这不是我要查找的结果。这是正常的行为还是什么?

3 个答案:

答案 0 :(得分:8)

Symfony\Component\HttpFoundation\Request::isXmlHttpRequest()是一种简单的实用程序方法,用于检查HTTP请求是否带有值为X-Requested-With的{​​{1}}标头。所以它和XMLHttpRequest标题一样可靠。

然而,这并不重要。需要注意的重要事项是,当用户点击后退按钮时,浏览器会向服务器发送新的HTTP请求。它只是从内部内存/缓存中恢复页面。

答案 1 :(得分:4)

我知道这是一个老问题,但同样的问题引起了我的注意,所以我想我还是会写一个答案。

在大多数情况下,您可以通过将onUnload处理程序附加到窗口来使后退按钮缓存无效,如下所示:

window.addEventListener('unload',function(){});

或者,如果您更喜欢jQuery:

$(window).unload(function(){});

但是,由于你的AJAX响应是JSON,显然不可能,因为你不能包含脚本片段。在这种情况下,我认为最好的想法是设置cache-control: no-store标题,以便浏览器不会尝试缓存结果。

你可以使用Symfony2在OP的情况下使用:

return new Response($res , 200 , array(
    'Content-Type' => 'application/json',
    'Cache-Control' => 'no-store',
));

或更一般的PHP:

header('Cache-Control: no-store');

这里有一个警告,它可能会降低你的性能,取决于你的应用程序的结构,在这种情况下,你最好的选择可能只是为你的AJAX调用使用不同的URL。很糟糕,我知道。

您可以在bfcache here上找到一些文档,这些文档在不同情况下可能更有帮助。

答案 2 :(得分:0)

浏览器仅使用url和请求方法(GET,POST等)作为密钥来缓存响应。

如果您希望浏览器识别其他变体,可以通过在响应中设置Vary标头来告知它。因此,在您的情况下,您希望告诉浏览器服务器的响应将根据请求中是否设置了“X-Requested-With”标头而有所不同。

以下是如何操作:

$response = new Response();

$response->setVary("X-Requested-With"); // <=========== Set the Vary header

if($request->isXmlHttpRequest()) {
    //...
}

return $response;

注意:您要在两个版本的响应上设置Vary标头(这就是为什么我将它设置在if语句之外)。