4 * This file is part of the Symfony package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * This code is partially based on the Rack-Cache library by Ryan Tomayko,
9 * which is released under the MIT license.
10 * (based on commit 02d2b48d75bcb63cf1c0c7149c077ad256542801)
12 * For the full copyright and license information, please view the LICENSE
13 * file that was distributed with this source code.
16 namespace Symfony\Component\HttpKernel\HttpCache;
18 use Symfony\Component\HttpFoundation\Response;
21 * ResponseCacheStrategy knows how to compute the Response cache HTTP header
22 * based on the different response cache headers.
24 * This implementation changes the master response TTL to the smallest TTL received
25 * or force validation if one of the surrogates has validation cache strategy.
27 * @author Fabien Potencier <fabien@symfony.com>
29 class ResponseCacheStrategy implements ResponseCacheStrategyInterface
31 private $cacheable = true;
32 private $embeddedResponses = 0;
33 private $ttls = array();
34 private $maxAges = array();
35 private $isNotCacheableResponseEmbedded = false;
40 public function add(Response $response)
42 if ($response->isValidateable()) {
43 $this->cacheable = false;
45 $maxAge = $response->getMaxAge();
46 $this->ttls[] = $response->getTtl();
47 $this->maxAges[] = $maxAge;
49 if (null === $maxAge) {
50 $this->isNotCacheableResponseEmbedded = true;
54 ++$this->embeddedResponses;
60 public function update(Response $response)
62 // if we have no embedded Response, do nothing
63 if (0 === $this->embeddedResponses) {
67 // Remove validation related headers in order to avoid browsers using
68 // their own cache, because some of the response content comes from
69 // at least one embedded response (which likely has a different caching strategy).
70 if ($response->isValidateable()) {
71 $response->setEtag(null);
72 $response->setLastModified(null);
73 $this->cacheable = false;
76 if (!$this->cacheable) {
77 $response->headers->set('Cache-Control', 'no-cache, must-revalidate');
82 $this->ttls[] = $response->getTtl();
83 $this->maxAges[] = $response->getMaxAge();
85 if ($this->isNotCacheableResponseEmbedded) {
86 $response->headers->removeCacheControlDirective('s-maxage');
87 } elseif (null !== $maxAge = min($this->maxAges)) {
88 $response->setSharedMaxAge($maxAge);
89 $response->headers->set('Age', $maxAge - min($this->ttls));
91 $response->setMaxAge(0);