diff --git a/framework/web/HttpCache.php b/framework/web/HttpCache.php index e3cf17d..d98cf92 100644 --- a/framework/web/HttpCache.php +++ b/framework/web/HttpCache.php @@ -27,7 +27,7 @@ class HttpCache extends ActionFilter * ~~~ * * where `$action` is the [[Action]] object that this filter is currently handling; - * `$params` takes the value of [[params]]. + * `$params` takes the value of [[params]]. The callback should return a UNIX timestamp. */ public $lastModified; /** @@ -39,7 +39,8 @@ class HttpCache extends ActionFilter * ~~~ * * where `$action` is the [[Action]] object that this filter is currently handling; - * `$params` takes the value of [[params]]. The callback should return a string. + * `$params` takes the value of [[params]]. The callback should return a string serving + * as the seed for generating an Etag. */ public $etagSeed; /** @@ -62,7 +63,7 @@ class HttpCache extends ActionFilter public function beforeAction($action) { $requestMethod = Yii::$app->request->getRequestMethod(); - if ($requestMethod !== 'GET' && $requestMethod !== 'HEAD') { + if ($requestMethod !== 'GET' && $requestMethod !== 'HEAD' || $this->lastModified === null && $this->etagSeed === null) { return true; } @@ -75,29 +76,36 @@ class HttpCache extends ActionFilter $etag = $this->generateEtag($seed); } + $this->sendCacheControlHeader(); if ($etag !== null) { header("ETag: $etag"); } - $this->sendCacheControlHeader(); - if ($this->hasChanged($lastModified, $etag)) { + if ($this->validateCache($lastModified, $etag)) { + header('HTTP/1.1 304 Not Modified'); + return false; + } else { if ($lastModified !== null) { header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $lastModified) . ' GMT'); } return true; - } else { - header('HTTP/1.1 304 Not Modified'); - return false; } } - protected function hasChanged($lastModified, $etag) + /** + * Validates if the HTTP cache contains valid content. + * @param integer $lastModified the calculated Last-Modified value in terms of a UNIX timestamp. + * If null, the Last-Modified header will not be validated. + * @param string $etag the calculated ETag value. If null, the ETag header will not be validated. + * @return boolean whether the HTTP cache is still valid. + */ + protected function validateCache($lastModified, $etag) { - $changed = !isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) || @strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) < $lastModified; - if (!$changed && $etag !== null) { - $changed = !isset($_SERVER['HTTP_IF_NONE_MATCH']) || $_SERVER['HTTP_IF_NONE_MATCH'] !== $etag; + if ($lastModified !== null && (!isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) || @strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) < $lastModified)) { + return false; + } else { + return $etag === null || isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] === $etag; } - return $changed; } /** @@ -114,7 +122,7 @@ class HttpCache extends ActionFilter } /** - * Generates an Etag from a given seed string. + * Generates an Etag from the given seed string. * @param string $seed Seed for the ETag * @return string the generated Etag */