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