10

让我们考虑如下场景:

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

我的控制器如下所示:

/**
 * 
 *
 * @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,这不是我正在寻找的结果。这是正常行为还是什么?

4

3 回答 3

10

Symfony\Component\HttpFoundation\Request::isXmlHttpRequest()是一个简单的实用方法,用于检查 HTTP 请求是否带有X-Requested-With带有 value 的标头XMLHttpRequestX-Requested-With所以它和标题一样可靠。

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

于 2012-08-13T21:11:40.997 回答
4

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

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

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

或者,如果您更喜欢 jQuery:

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

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

您可以在 OP 的情况下使用 Symfony2 执行此操作:

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

或者对于更一般的 PHP:

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

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

您可以在此处找到有关 bfcache 的一些文档,这在不同情况下可能会更有帮助。

于 2013-04-28T14:29:00.277 回答
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 语句之外设置它的原因)。

于 2016-05-31T23:28:51.373 回答