142

我正在尝试使用http缓存。在我的控制器中,我设置了如下响应:

$response->setPublic();
$response->setMaxAge(120);
$response->setSharedMaxAge(120);
$response->setLastModified($lastModifiedAt);

开发模式

在开发环境中,第一个响应是 200,带有以下标头:

cache-control:max-age=120, public, s-maxage=120
last-modified:Wed, 29 Feb 2012 19:00:00 GMT

在接下来的 2 分钟内,每个响应都是带有以下标题的 304:

cache-control:max-age=120, public, s-maxage=120

这基本上是我所期望的。

产品模式

在 prod 模式下,响应标头是不同的。请注意,在 app.php 中,我将内核包装在 AppCache 中。

第一个响应是带有以下标题的 200:

cache-control:must-revalidate, no-cache, private
last-modified:Thu, 01 Mar 2012 11:17:35 GMT

所以这是一个私有的无缓存响应。

下一个请求几乎都是我所期望的。带有以下标头的 304:

cache-control:max-age=120, public, s-maxage=120

我应该担心吗?这是预期的行为吗?

如果我将 Varnish 或 Akamai 服务器放在它前面会发生什么?

我做了一些调试,我认为响应是私有的,因为最后修改的标头。HttpCache 内核使用 EsiResponseCacheStrategy来更新缓存的响应(HttpCache::handle()方法)。

if (HttpKernelInterface::MASTER_REQUEST === $type) {
    $this->esiCacheStrategy->update($response);
}

如果 EsiResponseCacheStrategy 使用 Last-Response 或 ETag(EsiResponseCacheStrategy::add()方法) ,则EsiResponseCacheStrategy会将响应变为不可缓存:

if ($response->isValidateable()) {
    $this->cacheable = false;
} else {
    // ... 
}

如果 Last-Response 或 ETag 标头存在,则Response::isValidateable()返回 true。

它会导致覆盖 Cache-Control 标头EsiResponseCacheStrategy::update()方法):

if (!$this->cacheable) {
    $response->headers->set('Cache-Control', 'no-cache, must-revalidate');

    return;
}

我在 Symfony2 用户组上问了这个问题,但到目前为止我没有得到答案:https ://groups.google.com/d/topic/symfony2/6lpln11POq8/discussion

更新。

由于我不再能够访问原始代码,因此我尝试使用最新的 Symfony 标准版重现该场景

响应标头现在更加一致,但似乎仍然是错误的。

一旦我Last-Modified在响应上设置了标题,浏览器做出的第一个响应就有:

Cache-Control:must-revalidate, no-cache, private

第二个响应有一个预期:

Cache-Control:max-age=120, public, s-maxage=120

如果我避免发送If-Modified-Since标头,每个请求都会返回must-revalidate, no-cache, private.

prod如果请求是在环境中提出的,则无关紧要dev

4

2 回答 2

9

我遇到了同样的问题。我必须提供我的 CDN 的“公共”标题。默认情况下,在 prod 模式下启用网关缓存时,它会返回 200 OK 和私有,nocache 必须验证标头。

我以这种方式解决了问题。

在 app.php 中,在向用户发送响应 ($respond->send) 之前,我已将缓存控制标头覆盖为空白并将缓存标头设置为公共和最大年龄(某个值)。

//来自app.php的代码片段

    $response = $kernel->handle($request);
    $response->headers->set('Cache-Control', '');
    $response->setPublic();
    $response->setMaxAge(86400);
    $response->send();        
于 2014-02-09T09:02:27.850 回答
-4

您所经历的行为是有意的。Symfony2 文档明确描述了使用privatepublic的情况,默认为private

于 2013-10-22T20:30:50.953 回答