Fix that ESI/SSI processing can turn a \"private\" response \"public\"

This commit is contained in:
Matthias Pigulla 2018-03-22 20:40:31 +01:00 committed by Fabien Potencier
parent 2349e977ff
commit 3d27b5946d
3 changed files with 29 additions and 5 deletions

View File

@ -507,13 +507,19 @@ class Response
} }
/** /**
* Returns true if the response is worth caching under any circumstance. * Returns true if the response may safely be kept in a shared (surrogate) cache.
* *
* Responses marked "private" with an explicit Cache-Control directive are * Responses marked "private" with an explicit Cache-Control directive are
* considered uncacheable. * considered uncacheable.
* *
* Responses with neither a freshness lifetime (Expires, max-age) nor cache * Responses with neither a freshness lifetime (Expires, max-age) nor cache
* validator (Last-Modified, ETag) are considered uncacheable. * validator (Last-Modified, ETag) are considered uncacheable because there is
* no way to tell when or how to remove them from the cache.
*
* Note that RFC 7231 and RFC 7234 possibly allow for a more permissive implementation,
* for example "status codes that are defined as cacheable by default [...]
* can be reused by a cache with heuristic expiration unless otherwise indicated"
* (https://tools.ietf.org/html/rfc7231#section-6.1)
* *
* @return bool true if the response is worth caching, false otherwise * @return bool true if the response is worth caching, false otherwise
*/ */

View File

@ -72,7 +72,7 @@ class ResponseCacheStrategy implements ResponseCacheStrategyInterface
$response->setLastModified(null); $response->setLastModified(null);
} }
if (!$response->isFresh()) { if (!$response->isFresh() || !$response->isCacheable()) {
$this->cacheable = false; $this->cacheable = false;
} }

View File

@ -175,8 +175,26 @@ class ResponseCacheStrategyTest extends TestCase
$cacheStrategy->update($masterResponse); $cacheStrategy->update($masterResponse);
$this->assertTrue($masterResponse->headers->hasCacheControlDirective('private')); $this->assertTrue($masterResponse->headers->hasCacheControlDirective('private'));
// Not sure if we should pass "max-age: 60" in this case, as long as the response is private and $this->assertFalse($masterResponse->headers->hasCacheControlDirective('public'));
// that's the more conservative of both the master and embedded response...? }
public function testEmbeddingPublicResponseDoesNotMakeMainResponsePublic()
{
$cacheStrategy = new ResponseCacheStrategy();
$masterResponse = new Response();
$masterResponse->setPrivate(); // this is the default, but let's be explicit
$masterResponse->setMaxAge(100);
$embeddedResponse = new Response();
$embeddedResponse->setPublic();
$embeddedResponse->setSharedMaxAge(100);
$cacheStrategy->add($embeddedResponse);
$cacheStrategy->update($masterResponse);
$this->assertTrue($masterResponse->headers->hasCacheControlDirective('private'));
$this->assertFalse($masterResponse->headers->hasCacheControlDirective('public'));
} }
public function testResponseIsExiprableWhenEmbeddedResponseCombinesExpiryAndValidation() public function testResponseIsExiprableWhenEmbeddedResponseCombinesExpiryAndValidation()