如果使用AppCache(Symfony2),第一个响应是私有的,这样可以吗?

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

在接下来的两分钟内,每个响应都是一个带有以下头部信息的304响应:
cache-control:max-age=120, public, s-maxage=120

这基本上是我期望的内容。 生产模式 在生产模式下,响应头是不同的。请注意,在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服务器会发生什么?

我进行了一些调试,发现响应是私有的,因为有last-modified头。HttpCache内核使用EsiResponseCacheStrategy更新缓存响应(HttpCache::handle()方法)。

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

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

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

Response::isValidateable()会在最后的响应或者ETag头部存在时返回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标准版reproduce the scenario with the latest Symfony standard edition来重现场景。
响应头现在更加一致,但仍然似乎是错误的。
只要我在响应中设置了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"环境中进行。

3
当我禁用$kernel = new AppCache($kernel);时,它对我显示为公开。但是接下来它将始终响应代码200…我使用反向代理Nginx。 - Michael
1
我已经无法访问那个项目了,所以无法确认这一点。我记得控制器是默认的,并启用了AppCache。 - Jakub Zalas
1
@Florian 我尝试重现这个问题,并且在最新的Symfony版本中得到了稍微不同的行为(请参见更新)。 - Jakub Zalas
这可能是客户端和服务器之间存在微小时间差的情况吗? - Marek
2
你能否在AppCache的getOptions()中设置debug=>true,以便获取X-Symfony-Cache头部信息? - denkiryokuhatsuden
显示剩余5条评论
2个回答

9

我曾经遇到了同样的问题。我不得不在我的cdn上提供“公共”头文件。默认情况下,当在生产模式启用网关缓存时,它会返回带有私有、无缓存必须验证头的200 OK。

我通过以下方式解决了这个问题。

在 app.php 中,在将响应发送给用户之前($respond->send),我重写了缓存控制头为空,并设置了缓存头为public和max age(一些值)。

// app.php中的代码片段

    $response = $kernel->handle($request);
    $response->headers->set('Cache-Control', '');
    $response->setPublic();
    $response->setMaxAge(86400);
    $response->send();        

你是否在控制器中将回复设置为公开,但实际上收到了私人回复? - Jakub Zalas
是的,如果我启用网关缓存并在生产模式下运行它。我需要上述解决方案来处理静态内容。 - srikanthsatturi

-4
您所遇到的行为是有意的。Symfony2文档明确描述了使用privatepublic的情况,其中默认为private

这不是我的案例,抱歉。 - Jakub Zalas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接