diff --git a/composer.json b/composer.json index f1e0f34..4ac213e 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "psr/http-message": "^1.0" }, "require-dev": { - "slim/slim": "dev-develop" + "slim/slim": "3.x-dev" }, "autoload": { "psr-4": { diff --git a/src/Cache.php b/src/Cache.php index 948070b..56eaf2b 100644 --- a/src/Cache.php +++ b/src/Cache.php @@ -22,16 +22,25 @@ class Cache */ protected $maxAge; + /** + * Cache-Control includes must-revalidate flag + * + * @var bool + */ + protected $mustRevalidate; + /** * Create new HTTP cache * - * @param string $type The cache type: "public" or "private" - * @param int $maxAge The maximum age of client-side cache + * @param string $type The cache type: "public" or "private" + * @param int $maxAge The maximum age of client-side cache + * @param bool $mustRevalidate must-revalidate */ - public function __construct($type = 'private', $maxAge = 86400) + public function __construct($type = 'private', $maxAge = 86400, $mustRevalidate = false) { $this->type = $type; $this->maxAge = $maxAge; + $this->mustRevalidate = $mustRevalidate; } /** @@ -50,9 +59,10 @@ public function __invoke(RequestInterface $request, ResponseInterface $response, // Cache-Control header if (!$response->hasHeader('Cache-Control')) { $response = $response->withHeader('Cache-Control', sprintf( - '%s, max-age=%s', + '%s, max-age=%s%s', $this->type, - $this->maxAge + $this->maxAge, + $this->mustRevalidate ? ', must-revalidate' : '' )); } diff --git a/src/CacheProvider.php b/src/CacheProvider.php index d7e52ed..3cfa5b3 100644 --- a/src/CacheProvider.php +++ b/src/CacheProvider.php @@ -21,26 +21,31 @@ public function register(Container $container) /** * Enable client-side HTTP caching * - * @param ResponseInterface $response PSR7 response object - * @param string $type Cache-Control type: "private" or "public" - * @param null|int|string $maxAge Maximum cache age (integer timestamp or datetime string) + * @param ResponseInterface $response PSR7 response object + * @param string $type Cache-Control type: "private" or "public" + * @param null|int|string $maxAge Maximum cache age (integer timestamp or datetime string) + * @param bool $mustRevalidate add option "must-revalidate" to Cache-Control * * @return ResponseInterface A new PSR7 response object with `Cache-Control` header * @throws InvalidArgumentException if the cache-control type is invalid */ - public function allowCache(ResponseInterface $response, $type = 'private', $maxAge = null) + public function allowCache(ResponseInterface $response, $type = 'private', $maxAge = null, $mustRevalidate = false) { if (!in_array($type, ['private', 'public'])) { throw new InvalidArgumentException('Invalid Cache-Control type. Must be "public" or "private".'); } $headerValue = $type; - if ($maxAge) { + if ($maxAge || is_integer($maxAge)) { if (!is_integer($maxAge)) { $maxAge = strtotime($maxAge); } $headerValue = $headerValue . ', max-age=' . $maxAge; } + if ($mustRevalidate) { + $headerValue = $headerValue . ", must-revalidate"; + } + return $response->withHeader('Cache-Control', $headerValue); } diff --git a/tests/CacheProviderTest.php b/tests/CacheProviderTest.php index ebaf082..b7e6b68 100644 --- a/tests/CacheProviderTest.php +++ b/tests/CacheProviderTest.php @@ -16,6 +16,16 @@ public function testAllowCache() $this->assertEquals('private, max-age=43200', $cacheControl); } + public function testAllowCacheWithMustRevalidate() + { + $cacheProvider = new CacheProvider(); + $res = $cacheProvider->allowCache(new Response(), 'private', 43200, true); + + $cacheControl = $res->getHeaderLine('Cache-Control'); + + $this->assertEquals('private, max-age=43200, must-revalidate', $cacheControl); + } + public function testDenyCache() { $cacheProvider = new CacheProvider(); diff --git a/tests/CacheTest.php b/tests/CacheTest.php index 38bc245..28cc2e7 100644 --- a/tests/CacheTest.php +++ b/tests/CacheTest.php @@ -37,6 +37,21 @@ public function testCacheControlHeader() $this->assertEquals('public, max-age=86400', $cacheControl); } + public function testCacheControlHeaderWithMustRevalidate() + { + $cache = new Cache('private', 86400, true); + $req = $this->requestFactory(); + $res = new Response(); + $next = function (Request $req, Response $res) { + return $res; + }; + $res = $cache($req, $res, $next); + + $cacheControl = $res->getHeaderLine('Cache-Control'); + + $this->assertEquals('private, max-age=86400, must-revalidate', $cacheControl); + } + public function testCacheControlHeaderDoesNotOverrideExistingHeader() { $cache = new Cache('public', 86400);