From bb80139c3f2843ec627cf1761977753ae3e78c0d Mon Sep 17 00:00:00 2001 From: Bilal Amarni Date: Fri, 26 Apr 2013 14:05:25 +0200 Subject: [PATCH] [HttpCache] remove validation related headers when needed --- .../HttpCache/EsiResponseCacheStrategy.php | 27 ++++++++++++------ .../HttpKernel/HttpCache/HttpCache.php | 4 +-- .../Tests/HttpCache/HttpCacheTest.php | 28 +++++++++++++++++++ 3 files changed, 49 insertions(+), 10 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/HttpCache/EsiResponseCacheStrategy.php b/src/Symfony/Component/HttpKernel/HttpCache/EsiResponseCacheStrategy.php index c5ec81051fb3..6384af9660a8 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/EsiResponseCacheStrategy.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/EsiResponseCacheStrategy.php @@ -29,13 +29,12 @@ class EsiResponseCacheStrategy implements EsiResponseCacheStrategyInterface { private $cacheable = true; + private $embeddedResponses = 0; private $ttls = array(); private $maxAges = array(); /** - * Adds a Response. - * - * @param Response $response + * {@inheritdoc} */ public function add(Response $response) { @@ -45,26 +44,38 @@ public function add(Response $response) $this->ttls[] = $response->getTtl(); $this->maxAges[] = $response->getMaxAge(); } + + $this->embeddedResponses++; } /** - * Updates the Response HTTP headers based on the embedded Responses. - * - * @param Response $response + * {@inheritdoc} */ public function update(Response $response) { - // if we only have one Response, do nothing - if (1 === count($this->ttls)) { + // if we have no embedded Response, do nothing + if (0 === $this->embeddedResponses) { return; } + // Remove validation related headers in order to avoid browsers using + // their own cache, because some of the response content comes from + // at least one embedded response (which likely has a different caching strategy). + if ($response->isValidateable()) { + $response->setEtag(null); + $response->setLastModified(null); + $this->cacheable = false; + } + if (!$this->cacheable) { $response->headers->set('Cache-Control', 'no-cache, must-revalidate'); return; } + $this->ttls[] = $response->getTtl(); + $this->maxAges[] = $response->getMaxAge(); + if (null !== $maxAge = min($this->maxAges)) { $response->setSharedMaxAge($maxAge); $response->headers->set('Age', $maxAge - min($this->ttls)); diff --git a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php index 69e938881449..3f37366a8489 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php @@ -205,10 +205,10 @@ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQ } if (null !== $this->esi) { - $this->esiCacheStrategy->add($response); - if (HttpKernelInterface::MASTER_REQUEST === $type) { $this->esiCacheStrategy->update($response); + } else { + $this->esiCacheStrategy->add($response); } } diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php index 4cdd5f60e1f0..448ebc362bf3 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php @@ -1075,4 +1075,32 @@ public function testXForwarderForHeaderForPassRequests() $this->assertEquals('10.0.0.1', $this->kernel->getBackendRequest()->headers->get('X-Forwarded-For')); } + + public function testEsiCacheRemoveValidationHeadersIfEmbeddedResponses() + { + $time = new \DateTime; + + $responses = array( + array( + 'status' => 200, + 'body' => '', + 'headers' => array( + 'Surrogate-Control' => 'content="ESI/1.0"', + 'ETag' => 'hey', + 'Last-Modified' => $time->format(DATE_RFC2822), + ), + ), + array( + 'status' => 200, + 'body' => 'Hey!', + 'headers' => array(), + ), + ); + + $this->setNextResponses($responses); + + $this->request('GET', '/', array(), array(), true); + $this->assertNull($this->response->getETag()); + $this->assertNull($this->response->getLastModified()); + } }