Is it fine if first response is private with AppCache (Symfony2)?
I'm trying to use http caching. In my controller I'm setting a response as follows:
$response->setPublic();
$response->setMaxAge(120);
$response->setSharedMaxAge(120);
$response->setLastModified($lastModifiedAt);
dev mode
In dev environment first response is a 200 with following headers:
cache-control:max-age=120, public, s-maxage=120
last-modified:Wed, 29 Feb 2012 19:00:00 GMT
For next 2 minutes every response is a 304 with following headers:
cache-control:max-age=120, public, s-maxage=120
This is basically what I expect it to be.
prod mode
In prod mode response headers are different. Note that in app.php I wrap the kernel in AppCache.
First response is a 200 with following headers:
cache-control:must-revalidate, no-cache, private
last-modified:Thu, 01 Mar 2012 11:17:35 GMT
So it's a private no-cache response.
Every next request is pretty much what I'd expect it to be; a 304 with following headers:
cache-control:max-age=120, public, s-maxage=120
Should I worry about it? Is it an expected behaviour?
What will happen if I put Varnish or Akamai server in front of it?
I did a bit of debugging and I figured that response is private because of last-modified header. HttpCache kernel uses EsiResponseCacheStrategy to update the cached response (HttpCache::handle() method).
if (HttpKernelInterface::MASTER_REQUEST === $type) {
$this->esiCacheStrategy->update($response);
}
EsiResponseCacheStrategy turns a response into non cacheable if it uses either Last-Response or ETag (EsiResponseCacheStrategy::add() method):
if ($response->isValidateable()) {
$this->cacheable = false;
} else {
// ...
}
Response::isValidateable() returns true if Last-Response or ETag header is present.
It results in overwriting the Cache-Control header (EsiResponseCacheStrategy::update() method):
if (!$this->cacheable) {
$response->headers->set('Cache-Control', 'no-cache, must-revalidate');
return;
}
I asked this question on Symfony2 user group but I didn't get an answer so far: https://groups.google.com/d/topic/symfony2/6lpln11POq8/discussion
Update.
Since I no longer have access to the original code I tried to reproduce the scenario with the latest Symfony standard edition.
Response headers are more consistent now, but still seem to be wrong.
As soon as I set a Last-Modified
header on the response, the first response made by a browser has a:
Cache-Control:must-revalidate, no-cache, private
Second response has an expected:
Cache-Control:max-age=120, public, s-maxage=120
If I avoid sending If-Modified-Since
header, every request returns must-revalidate, no-cache, private
.
It doesn't matter if the request was made in prod
or dev
environment anymore.
Solution 1:
I have faced same problem. I had to supply 'public' headers my cdn. By default when gateway caching is enabled in prod mode, it returns 200 OK with private, nocache must validate headers.
I solved problem this way.
In app.php, before I send response to user ($respond->send), I have overwritten the cache control header to blank and set cache headers to public and max age(some value).
//code snippet from app.php
$response = $kernel->handle($request);
$response->headers->set('Cache-Control', '');
$response->setPublic();
$response->setMaxAge(86400);
$response->send();