From 273e5b96ece41b6b307f105cc1d3ac96fc028846 Mon Sep 17 00:00:00 2001 From: jinora Date: Mon, 5 Aug 2013 23:37:30 +0200 Subject: [PATCH 1/5] HTTP cache methods publicCache(), privateCache(), sendCacheHeaders() added noCache() refactored tests added --- src/Klein/Response.php | 82 +++++++++++++++++++++++++++++- tests/Klein/Tests/ResponseTest.php | 59 +++++++++++++++++---- 2 files changed, 128 insertions(+), 13 deletions(-) diff --git a/src/Klein/Response.php b/src/Klein/Response.php index ef89f54b..4037d75e 100644 --- a/src/Klein/Response.php +++ b/src/Klein/Response.php @@ -25,6 +25,19 @@ class Response { + /** + * Class constants + */ + + /** Public HTTP cache flag */ + const PUBLIC_CACHE = 'public_cache'; + + /** Private HTTP cache flag */ + const PRIVATE_CACHE = 'private_cache'; + + /** No HTTP cache flag */ + const NO_CACHE = 'no_cache'; + /** * Class properties */ @@ -103,6 +116,13 @@ class Response */ public $chunked = false; + /** + * Cache control flag + * + * @var string + * @access public + */ + public $cache_control = self::NO_CACHE; /** * Methods @@ -341,6 +361,36 @@ protected function httpStatusLine() return sprintf('HTTP/%s %s', $this->protocol_version, $this->status); } + /** + * Send HTTP cache headers + * + * @param boolean $override + * @access public + * @return Response + */ + public function sendCacheHeaders($override = false) + { + + if (headers_sent() && !$override) { + return $this; + } + + switch ($this->cache_control) { + case self::PUBLIC_CACHE: + header('Cache-Control: public'); + break; + case self::PRIVATE_CACHE: + header('Cache-Control: private'); + break; + case self::NO_CACHE: + header('Pragma: no-cache'); + header('Cache-Control: no-store, no-cache'); + break; + } + + return $this; + } + /** * Send our HTTP headers * @@ -358,6 +408,9 @@ public function sendHeaders($cookies_also = true, $override = false) // Send our HTTP status line header($this->httpStatusLine()); + //Send HTTP cache headers + $this->sendCacheHeaders($override); + // Iterate through our Headers data collection and send each header foreach ($this->headers as $key => $value) { header($key .': '. $value, false); @@ -535,6 +588,32 @@ public function cookie( return $this; } + /** + * Tell the browser and network caches (e.g. Varnish) to publicly cache the response + * + * @access public + * @return Response + */ + public function publicCache() + { + $this->cache_control = self::PUBLIC_CACHE; + + return $this; + } + + /** + * Tell the browser to privately cache the response + * + * @access public + * @return Response + */ + public function privateCache() + { + $this->cache_control = self::PRIVATE_CACHE; + + return $this; + } + /** * Tell the browser not to cache the response * @@ -543,8 +622,7 @@ public function cookie( */ public function noCache() { - $this->header('Pragma', 'no-cache'); - $this->header('Cache-Control', 'no-store, no-cache'); + $this->cache_control = self::NO_CACHE; return $this; } diff --git a/tests/Klein/Tests/ResponseTest.php b/tests/Klein/Tests/ResponseTest.php index 855f2b65..41a29295 100644 --- a/tests/Klein/Tests/ResponseTest.php +++ b/tests/Klein/Tests/ResponseTest.php @@ -201,6 +201,21 @@ public function testSendHeaders() $this->expectOutputString(null); } + /** + * Yes, testing headers really is a pain in the ass. ;) + * + * Technically... we can't. So, yea. + */ + public function testSendCacheHeaders() + { + $response = new Response('beep bloop blop beep boop'); + $response->noCache(); + + $response->sendCacheHeaders(); + + $this->expectOutputString(null); + } + /** * Testing cookies is exactly like testing headers * ... So, yea. @@ -283,16 +298,40 @@ public function testHeader() } } + public function testPublicCache() + { + $response = new Response(); + + // Make sure cache control is not initially publicCache + $response->cache_control = null; + + $response->publicCache(); + + $this->assertEquals(Response::PUBLIC_CACHE, $response->cache_control); + } + + public function testPrivateCache() + { + $response = new Response(); + + // Make sure cache control is not initially privateCache + $response->cache_control = null; + + $response->privateCache(); + + $this->assertEquals(Response::PRIVATE_CACHE, $response->cache_control); + } + public function testNoCache() { $response = new Response(); - // Make sure the headers are initially empty - $this->assertEmpty($response->headers()->all()); + // Make sure cache control is not initially noCache + $response->cache_control = null; $response->noCache(); - $this->assertContains('no-cache', $response->headers()->all()); + $this->assertEquals(Response::NO_CACHE, $response->cache_control); } public function testRedirect() @@ -337,6 +376,9 @@ function ($request, $response, $service) use ($file_name, $file_mime) { file_get_contents(__FILE__) ); + //Assert noCache was set + $this->assertEquals(Response::NO_CACHE, $this->klein_app->response()->cache_control); + // Assert headers were passed $this->assertEquals( $file_mime, @@ -378,15 +420,10 @@ function ($request, $response, $service) use ($test_object) { json_encode($test_object) ); + //Assert noCache was set + $this->assertEquals(Response::NO_CACHE, $this->klein_app->response()->cache_control); + // Assert headers were passed - $this->assertEquals( - 'no-cache', - $this->klein_app->response()->headers()->get('Pragma') - ); - $this->assertEquals( - 'no-store, no-cache', - $this->klein_app->response()->headers()->get('Cache-Control') - ); $this->assertEquals( 'application/json', $this->klein_app->response()->headers()->get('Content-Type') From 5b4835810b6711b50815880cb62289521a99b2b3 Mon Sep 17 00:00:00 2001 From: jinora Date: Tue, 6 Aug 2013 10:28:16 +0200 Subject: [PATCH 2/5] Conventions fix --- src/Klein/Response.php | 9 ++++----- tests/Klein/Tests/ResponseTest.php | 14 ++++++++++---- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/Klein/Response.php b/src/Klein/Response.php index 4037d75e..6121aa1b 100644 --- a/src/Klein/Response.php +++ b/src/Klein/Response.php @@ -30,13 +30,13 @@ class Response */ /** Public HTTP cache flag */ - const PUBLIC_CACHE = 'public_cache'; + const PUBLIC_CACHE = 0; /** Private HTTP cache flag */ - const PRIVATE_CACHE = 'private_cache'; + const PRIVATE_CACHE = 1; /** No HTTP cache flag */ - const NO_CACHE = 'no_cache'; + const NO_CACHE = 2; /** * Class properties @@ -370,7 +370,6 @@ protected function httpStatusLine() */ public function sendCacheHeaders($override = false) { - if (headers_sent() && !$override) { return $this; } @@ -408,7 +407,7 @@ public function sendHeaders($cookies_also = true, $override = false) // Send our HTTP status line header($this->httpStatusLine()); - //Send HTTP cache headers + // Send HTTP cache headers $this->sendCacheHeaders($override); // Iterate through our Headers data collection and send each header diff --git a/tests/Klein/Tests/ResponseTest.php b/tests/Klein/Tests/ResponseTest.php index 41a29295..dfb77391 100644 --- a/tests/Klein/Tests/ResponseTest.php +++ b/tests/Klein/Tests/ResponseTest.php @@ -376,8 +376,11 @@ function ($request, $response, $service) use ($file_name, $file_mime) { file_get_contents(__FILE__) ); - //Assert noCache was set - $this->assertEquals(Response::NO_CACHE, $this->klein_app->response()->cache_control); + // Assert noCache was set + $this->assertEquals( + Response::NO_CACHE, + $this->klein_app->response()->cache_control + ); // Assert headers were passed $this->assertEquals( @@ -420,8 +423,11 @@ function ($request, $response, $service) use ($test_object) { json_encode($test_object) ); - //Assert noCache was set - $this->assertEquals(Response::NO_CACHE, $this->klein_app->response()->cache_control); + // Assert noCache was set + $this->assertEquals( + Response::NO_CACHE, + $this->klein_app->response()->cache_control + ); // Assert headers were passed $this->assertEquals( From ea5b5e8814964c8c002a9f88d6a12185a70b2751 Mon Sep 17 00:00:00 2001 From: jinora Date: Tue, 6 Aug 2013 14:07:53 +0200 Subject: [PATCH 3/5] HttpResponseCache class added --- src/Klein/HttpResponseCache.php | 398 ++++++++++++++++++++ tests/Klein/Tests/HttpResponseCacheTest.php | 217 +++++++++++ 2 files changed, 615 insertions(+) create mode 100644 src/Klein/HttpResponseCache.php create mode 100644 tests/Klein/Tests/HttpResponseCacheTest.php diff --git a/src/Klein/HttpResponseCache.php b/src/Klein/HttpResponseCache.php new file mode 100644 index 00000000..4f0ac436 --- /dev/null +++ b/src/Klein/HttpResponseCache.php @@ -0,0 +1,398 @@ + + * @author Trevor Suarez (Rican7) (contributor and v2 refactorer) + * @copyright (c) Chris O'Hara + * @link https://github.com/chriso/klein.php + * @license MIT + */ + +namespace Klein; + +/** + * HttpResponseCache + * + * HTTP cache headers manager + * + * @package Klein + */ +class HttpResponseCache +{ + + /** + * HTTP Cache-Control public indicator + * + * @var bool + */ + protected $public = false; + + /** + * HTTP Cache-Control private indicator + * + * @var bool + */ + protected $private = false; + + /** + * HTTP Cache-Control no-cache indicator + * + * @var bool + */ + protected $no_cache = false; + + /** + * HTTP Cache-Control no-store indicator + * + * @var bool + */ + protected $no_store = false; + + /** + * HTTP Cache-Control no-transform indicator + * + * @var bool + */ + protected $no_transform = false; + + /** + * HTTP Cache-Control must-revalidate indicator + * + * @var bool + */ + protected $must_revalidate = false; + + /** + * HTTP Cache-Control proxy-revalidate indicator + * + * @var bool + */ + protected $proxy_revalidate = false; + + /** + * HTTP Cache-Control max-age value + * + * @var int + */ + protected $max_age = 0; + + /** + * HTTP Cache-Control s-maxage value + * + * @var int + */ + protected $s_maxage = 0; + + /** + * HTTP Cache-Control cache-extension + * + * @var array + */ + protected $extensions = array(); + + + /** + * Set response public + * + * @param bool $public + * @return HttpResponseCache + */ + public function setPublic($public = true) + { + $this->public = (bool)$public; + $this->private = false; + $this->no_cache = false; + + return $this; + } + + /** + * Indicates whether is response public + * + * @return bool + */ + public function getPublic() + { + return $this->public; + } + + /** + * Set response private + * + * @param bool $private + * @return HttpResponseCache + */ + public function setPrivate($private = true) + { + $this->private = (bool)$private; + $this->public = false; + $this->no_cache = false; + + return $this; + } + + /** + * Indicates whether is response private + * + * @return bool + */ + public function getPrivate() + { + return $this->private; + } + + /** + * Set response non cacheable + * + * @param bool $no_cache + * @return HttpResponseCache + */ + public function setNoCache($no_cache = true) + { + $this->no_cache = (bool)$no_cache; + $this->public = false; + $this->private = false; + + return true; + } + + /** + * Indicates whether is response cacheable + * + * @return bool + */ + public function getNoCache() + { + return $this->no_cache; + } + + /** + * Set response not storable + * + * @param bool $no_store + * @return HttpResponseCache + */ + public function setNoStore($no_store = true) + { + $this->no_store = (bool)$no_store; + + return $this; + } + + /** + * Indicates whether is response storable + * + * @return bool + */ + public function getNoStore() + { + return $this->no_store; + } + + /** + * Set response cannot transform + * + * @param bool $no_transform + * @return HttpResponseCache + */ + public function setNoTransform($no_transform = true) + { + $this->no_transform = (bool)$no_transform; + + return $this; + } + + /** + * Indicates whether response can transform + * + * @return bool + */ + public function getNoTransform() + { + return $this->no_transform; + } + + /** + * Set cache must revalidate stored response + * + * @param $must_revalidate + * @return HttpResponseCache + */ + public function setMustRevalidate($must_revalidate = true) + { + $this->must_revalidate = (bool)$must_revalidate; + + return $this; + } + + /** + * Indicates whether cache must revalidate stored response + * + * @return boolean + */ + public function getMustRevalidate() + { + return $this->must_revalidate; + } + + /** + * Set shared cache must revalidate stored response + * + * @param $proxy_revalidate + * @return HttpResponseCache + */ + public function setProxyRevalidate($proxy_revalidate = true) + { + $this->proxy_revalidate = (bool)$proxy_revalidate; + + return $this; + } + + /** + * Indicates whether shared cache must revalidate stored response + * + * @return boolean + */ + public function getProxyRevalidate() + { + return $this->proxy_revalidate; + } + + /** + * Set cache lifetime + * + * @param $max_age + * @return HttpResponseCache + */ + public function setMaxAge($max_age) + { + $this->max_age = (int)$max_age; + + return $this; + } + + /** + * Get cache lifetime + * + * @return int + */ + public function getMaxAge() + { + return $this->max_age; + } + + /** + * Set shared cache lifetime + * + * @param $s_maxage + * @return HttpResponseCache + */ + public function setSMaxage($s_maxage) + { + $this->s_maxage = (int)$s_maxage; + + return $this; + } + + /** + * Get shared cache lifetime + * + * @return int + */ + public function getSMaxage() + { + return $this->s_maxage; + } + + /** + * Set custom Cache-Control param + * + * @param string $key + * @param string $value + * @return HttpResponseCache + */ + public function setExtension($key, $value = null) + { + $this->extensions[$key] = (string)$value; + + return $this; + } + + /** + * Get custom Cache-Control param + * + * @param string $key + * @return string + */ + public function getExtension($key) + { + return $this->extensions[$key]; + } + + + /** + * Generate header string + * + * @return string + */ + public function generateCacheControlString() + { + $headerString = ''; + + if ($this->no_cache) { + $headerString .= ' no-cache'; + } elseif ($this->private) { + $headerString .= ' private'; + } elseif ($this->public) { + $headerString .= ' public'; + } else { + $headerString .= ' no-cache'; + } + + if ($this->no_store) { + $headerString .= ' no-store'; + } + + if ($this->no_transform) { + $headerString .= ' no-transform'; + } + + if ($this->must_revalidate) { + $headerString .= ' must-revalidate'; + } + + if ($this->proxy_revalidate) { + $headerString .= ' proxy-revalidate'; + } + + if (is_integer($this->max_age)) { + $headerString .= ' max-age=' . $this->max_age; + } + + if (is_integer($this->s_maxage)) { + $headerString .= ' s-maxage=' . $this->s_maxage; + } + + foreach ($this->extensions as $extensionName => $extensionValue) { + + if ($extensionValue === '') { + $headerString .= ' ' . $extensionName; + } else { + $headerString .= ' ' . $extensionName . '=' . $extensionValue; + } + + } + + return 'Cache-Control: ' . trim($headerString); + } + + /** + * Send headers + */ + public function send() + { + + header($this->generateCacheControlString(), true); + } +} \ No newline at end of file diff --git a/tests/Klein/Tests/HttpResponseCacheTest.php b/tests/Klein/Tests/HttpResponseCacheTest.php new file mode 100644 index 00000000..f61c716e --- /dev/null +++ b/tests/Klein/Tests/HttpResponseCacheTest.php @@ -0,0 +1,217 @@ + + * @author Trevor Suarez (Rican7) (contributor and v2 refactorer) + * @copyright (c) Chris O'Hara + * @link https://github.com/chriso/klein.php + * @license MIT + */ + +namespace Klein\Tests; + + +use \Klein\HttpResponseCache; + +/** + * HttpResponseCacheTest + * + * @uses AbstractKleinTest + * @package Klein\Tests + */ +class HttpResponseCacheTest extends AbstractKleinTest +{ + public function testBasicExample() + { + $max_age = rand(1, 100); + $responseCache = new HttpResponseCache(); + + $responseCache->setPublic(); + $responseCache->setMaxAge($max_age); + $responseCache->setSMaxage($max_age); + + $CacheString = $responseCache->generateCacheControlString(); + $this->assertContains('Cache-Control: ', $CacheString); + $this->assertContains(' public', $CacheString); + $this->assertContains(' max-age=' . $max_age, $CacheString); + $this->assertContains(' s-maxage=' . $max_age, $CacheString); + + $this->assertNotContains(' private', $CacheString); + $this->assertNotContains(' no-cache', $CacheString); + $this->assertNotContains(' no-store', $CacheString); + } + + public function testGenerateCacheControlString() + { + $responseCache = new HttpResponseCache(); + + + $CacheString = $responseCache->generateCacheControlString(); + $this->assertContains('Cache-Control: ', $CacheString); + $this->assertContains(' no-cache', $CacheString); + } + + public function testPublicGetSet() + { + $responseCache = new HttpResponseCache(); + + $responseCache->setNoCache(); + $responseCache->setPrivate(); + $responseCache->setPublic(); + + $this->assertTrue($responseCache->getPublic()); + $this->assertFalse($responseCache->getPrivate()); + $this->assertFalse($responseCache->getNoCache()); + + $CacheString = $responseCache->generateCacheControlString(); + $this->assertContains('Cache-Control: ', $CacheString); + $this->assertContains(' public', $CacheString); + $this->assertNotContains(' private', $CacheString); + $this->assertNotContains(' no-cache', $CacheString); + } + + public function testPrivateGetSet() + { + $responseCache = new HttpResponseCache(); + + $responseCache->setPublic(); + $responseCache->setNoCache(); + $responseCache->setPrivate(); + + $this->assertTrue($responseCache->getPrivate()); + $this->assertFalse($responseCache->getPublic()); + $this->assertFalse($responseCache->getNoCache()); + + + $CacheString = $responseCache->generateCacheControlString(); + $this->assertContains('Cache-Control: ', $CacheString); + $this->assertContains(' private', $CacheString); + $this->assertNotContains(' public', $CacheString); + $this->assertNotContains(' no-cache', $CacheString); + } + + public function testNoCacheGetSet() + { + $responseCache = new HttpResponseCache(); + + $responseCache->setPublic(); + $responseCache->setPrivate(); + $responseCache->setNoCache(); + + $this->assertTrue($responseCache->getNoCache()); + $this->assertFalse($responseCache->getPublic()); + $this->assertFalse($responseCache->getPrivate()); + + + $CacheString = $responseCache->generateCacheControlString(); + $this->assertContains('Cache-Control: ', $CacheString); + $this->assertContains(' no-cache', $CacheString); + $this->assertNotContains(' public', $CacheString); + $this->assertNotContains(' private', $CacheString); + } + + /** + * @dataProvider methodProvider + */ + public function testOptionsGetSet($setMethod, $getMethod, $cacheString) + { + $responseCache = new HttpResponseCache(); + + $responseCache->{$setMethod}(true); + $this->assertTrue($responseCache->{$getMethod}()); + + // Test default Cache-Control + $generatedString = $responseCache->generateCacheControlString(); + $this->assertContains('Cache-Control: ', $generatedString); + $this->assertContains(' ' . $cacheString, $generatedString); + + + $responseCache->{$setMethod}(false); + $this->assertFalse($responseCache->{$getMethod}()); + + $generatedString = $responseCache->generateCacheControlString(); + $this->assertContains('Cache-Control: ', $generatedString); + $this->assertNotContains(' ' . $cacheString, $generatedString); + } + + public function methodProvider() + { + return array( + array('setNoStore', 'getNoStore', 'no-store'), + array('setNoTransform', 'getNoTransform', 'no-transform'), + array('setMustRevalidate', 'getMustRevalidate', 'must-revalidate'), + array('setProxyRevalidate', 'getProxyRevalidate', 'proxy-revalidate') + ); + } + + public function testMaxAgeGetSet() + { + $responseCache = new HttpResponseCache(); + $randomAge = rand(); + + $responseCache->setMaxAge($randomAge); + $this->assertEquals($randomAge, $responseCache->getMaxAge()); + + + $generatedString = $responseCache->generateCacheControlString(); + $this->assertContains('Cache-Control: ', $generatedString); + $this->assertContains(' max-age=' . $randomAge, $generatedString); + + + $newAge = $randomAge - 1; + $responseCache->setMaxAge($newAge); + $this->assertEquals($newAge, $responseCache->getMaxAge()); + + $generatedString = $responseCache->generateCacheControlString(); + $this->assertContains('Cache-Control: ', $generatedString); + $this->assertContains(' max-age=' . $newAge, $generatedString); + } + + public function testSMaxageGetSet() + { + $responseCache = new HttpResponseCache(); + $randomAge = rand(); + + $responseCache->setSMaxage($randomAge); + $this->assertEquals($randomAge, $responseCache->getSMaxage()); + + // Test default Cache-Control + $generatedString = $responseCache->generateCacheControlString(); + $this->assertContains('Cache-Control: ', $generatedString); + $this->assertContains(' s-maxage=' . $randomAge, $generatedString); + + + $newAge = $randomAge - 1; + $responseCache->setSMaxage($newAge); + $this->assertEquals($newAge, $responseCache->getSMaxage()); + + $generatedString = $responseCache->generateCacheControlString(); + $this->assertContains('Cache-Control: ', $generatedString); + $this->assertContains(' s-maxage=' . $newAge, $generatedString); + } + + public function testExtensionsGetSet() + { + $key = "Extension"; + $value = "Option"; + + $responseCache = new HttpResponseCache(); + + $responseCache->setExtension($key); + $this->assertEquals('', $responseCache->getExtension($key)); + + $generatedString = $responseCache->generateCacheControlString(); + $this->assertContains('Cache-Control: ', $generatedString); + $this->assertContains(' ' . $key, $generatedString); + $this->assertNotContains(' ' . $key . '=', $generatedString); + + + $responseCache->setExtension($key, $value); + $this->assertEquals($value, $responseCache->getExtension($key)); + + $generatedString = $responseCache->generateCacheControlString(); + $this->assertContains('Cache-Control: ', $generatedString); + $this->assertContains(' ' . $key . '=' . $value, $generatedString); + } +} From d045f472ede701ee26af99d46d3a2fd919b234d5 Mon Sep 17 00:00:00 2001 From: jinora Date: Tue, 6 Aug 2013 14:37:00 +0200 Subject: [PATCH 4/5] HttpResponseCache class added --- src/Klein/Response.php | 93 +++++------------------------- tests/Klein/Tests/ResponseTest.php | 75 +++++++----------------- 2 files changed, 36 insertions(+), 132 deletions(-) diff --git a/src/Klein/Response.php b/src/Klein/Response.php index 6121aa1b..40e38a7f 100644 --- a/src/Klein/Response.php +++ b/src/Klein/Response.php @@ -18,26 +18,13 @@ use \Klein\Exceptions\ResponseAlreadySentException; /** - * Response - * + * Response + * * @package Klein */ class Response { - /** - * Class constants - */ - - /** Public HTTP cache flag */ - const PUBLIC_CACHE = 0; - - /** Private HTTP cache flag */ - const PRIVATE_CACHE = 1; - - /** No HTTP cache flag */ - const NO_CACHE = 2; - /** * Class properties */ @@ -91,6 +78,14 @@ class Response */ protected $cookies; + /** + * HTTP response cache headers + * + * @var \Klein\HttpResponseCache + * @access protected + */ + protected $cache; + /** * Whether or not the response is "locked" from * any further modification @@ -116,13 +111,6 @@ class Response */ public $chunked = false; - /** - * Cache control flag - * - * @var string - * @access public - */ - public $cache_control = self::NO_CACHE; /** * Methods @@ -148,6 +136,7 @@ public function __construct($body = '', $status_code = null, array $headers = ar $this->headers = new HeaderDataCollection($headers); $this->cookies = new ResponseCookieDataCollection(); + $this->cache = new HttpResponseCache(); } /** @@ -361,35 +350,6 @@ protected function httpStatusLine() return sprintf('HTTP/%s %s', $this->protocol_version, $this->status); } - /** - * Send HTTP cache headers - * - * @param boolean $override - * @access public - * @return Response - */ - public function sendCacheHeaders($override = false) - { - if (headers_sent() && !$override) { - return $this; - } - - switch ($this->cache_control) { - case self::PUBLIC_CACHE: - header('Cache-Control: public'); - break; - case self::PRIVATE_CACHE: - header('Cache-Control: private'); - break; - case self::NO_CACHE: - header('Pragma: no-cache'); - header('Cache-Control: no-store, no-cache'); - break; - } - - return $this; - } - /** * Send our HTTP headers * @@ -408,7 +368,7 @@ public function sendHeaders($cookies_also = true, $override = false) header($this->httpStatusLine()); // Send HTTP cache headers - $this->sendCacheHeaders($override); + $this->cache->send(); // Iterate through our Headers data collection and send each header foreach ($this->headers as $key => $value) { @@ -587,32 +547,6 @@ public function cookie( return $this; } - /** - * Tell the browser and network caches (e.g. Varnish) to publicly cache the response - * - * @access public - * @return Response - */ - public function publicCache() - { - $this->cache_control = self::PUBLIC_CACHE; - - return $this; - } - - /** - * Tell the browser to privately cache the response - * - * @access public - * @return Response - */ - public function privateCache() - { - $this->cache_control = self::PRIVATE_CACHE; - - return $this; - } - /** * Tell the browser not to cache the response * @@ -621,7 +555,8 @@ public function privateCache() */ public function noCache() { - $this->cache_control = self::NO_CACHE; + $this->cache->setNoCache(); + $this->cache->setNoStore(); return $this; } diff --git a/tests/Klein/Tests/ResponseTest.php b/tests/Klein/Tests/ResponseTest.php index dfb77391..52c07b8a 100644 --- a/tests/Klein/Tests/ResponseTest.php +++ b/tests/Klein/Tests/ResponseTest.php @@ -15,6 +15,7 @@ use \Klein\Klein; use \Klein\Response; use \Klein\HttpStatus; +use \Klein\HttpResponseCache; use \Klein\DataCollection\HeaderDataCollection; use \Klein\DataCollection\ResponseCookieDataCollection; use \Klein\Exceptions\LockedResponseException; @@ -22,8 +23,8 @@ use \Klein\Tests\Mocks\MockRequestFactory; /** - * ResponsesTest - * + * ResponsesTest + * * @uses AbstractKleinTest * @package Klein\Tests */ @@ -111,6 +112,19 @@ public function testCookiesGetter() $this->assertTrue($response->cookies() instanceof ResponseCookieDataCollection); } + public function testCacheGetSet() + { + $response = new Response(); + + $this->assertInternalType('object', $response->cache()); + $this->assertTrue($response->cache() instanceof HttpResponseCache); + + $newCache = new HttpResponseCache(); + $response->cache($newCache); + + $this->assertEquals($newCache, $response->cache()); + } + public function testPrepend() { $response = new Response('ein'); @@ -201,21 +215,6 @@ public function testSendHeaders() $this->expectOutputString(null); } - /** - * Yes, testing headers really is a pain in the ass. ;) - * - * Technically... we can't. So, yea. - */ - public function testSendCacheHeaders() - { - $response = new Response('beep bloop blop beep boop'); - $response->noCache(); - - $response->sendCacheHeaders(); - - $this->expectOutputString(null); - } - /** * Testing cookies is exactly like testing headers * ... So, yea. @@ -298,40 +297,14 @@ public function testHeader() } } - public function testPublicCache() - { - $response = new Response(); - - // Make sure cache control is not initially publicCache - $response->cache_control = null; - - $response->publicCache(); - - $this->assertEquals(Response::PUBLIC_CACHE, $response->cache_control); - } - - public function testPrivateCache() - { - $response = new Response(); - - // Make sure cache control is not initially privateCache - $response->cache_control = null; - - $response->privateCache(); - - $this->assertEquals(Response::PRIVATE_CACHE, $response->cache_control); - } - public function testNoCache() { $response = new Response(); - // Make sure cache control is not initially noCache - $response->cache_control = null; - $response->noCache(); - $this->assertEquals(Response::NO_CACHE, $response->cache_control); + $this->assertTrue($response->cache()->getNoCache()); + $this->assertTrue($response->cache()->getNoStore()); } public function testRedirect() @@ -377,10 +350,8 @@ function ($request, $response, $service) use ($file_name, $file_mime) { ); // Assert noCache was set - $this->assertEquals( - Response::NO_CACHE, - $this->klein_app->response()->cache_control - ); + $this->assertTrue($this->klein_app->response()->cache()->getNoCache()); + $this->assertTrue($this->klein_app->response()->cache()->getNoStore()); // Assert headers were passed $this->assertEquals( @@ -424,10 +395,8 @@ function ($request, $response, $service) use ($test_object) { ); // Assert noCache was set - $this->assertEquals( - Response::NO_CACHE, - $this->klein_app->response()->cache_control - ); + $this->assertTrue($this->klein_app->response()->cache()->getNoCache()); + $this->assertTrue($this->klein_app->response()->cache()->getNoStore()); // Assert headers were passed $this->assertEquals( From e1520e3f0ae0f9ea16d41c2308664e1e5af2cf8c Mon Sep 17 00:00:00 2001 From: jinora Date: Tue, 6 Aug 2013 14:42:07 +0200 Subject: [PATCH 5/5] HttpResponseCache class added --- src/Klein/Response.php | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/Klein/Response.php b/src/Klein/Response.php index 40e38a7f..14ad91cb 100644 --- a/src/Klein/Response.php +++ b/src/Klein/Response.php @@ -246,6 +246,27 @@ public function code($code = null) return $this->status->getCode(); } + /** + * Get (or set) the HTTP Cache-Control object + * + * @param null|HttpResponseCache $cache + * @access public + * @return HttpResponseCache|Response + */ + public function cache(HttpResponseCache $cache = null) + { + if (null !== $cache) { + // Require that the response be unlocked before changing it + $this->requireUnlocked(); + + $this->cache = $cache; + + return $this; + } + + return $this->cache; + } + /** * Prepend a string to the response's content body *