Commit 8724d803 by Qiang Xue

HttpCache WIP.

parent 1184e1e1
...@@ -27,7 +27,7 @@ class HttpCache extends ActionFilter ...@@ -27,7 +27,7 @@ class HttpCache extends ActionFilter
* ~~~ * ~~~
* *
* where `$action` is the [[Action]] object that this filter is currently handling; * 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; public $lastModified;
/** /**
...@@ -39,7 +39,8 @@ class HttpCache extends ActionFilter ...@@ -39,7 +39,8 @@ class HttpCache extends ActionFilter
* ~~~ * ~~~
* *
* where `$action` is the [[Action]] object that this filter is currently handling; * 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; public $etagSeed;
/** /**
...@@ -62,7 +63,7 @@ class HttpCache extends ActionFilter ...@@ -62,7 +63,7 @@ class HttpCache extends ActionFilter
public function beforeAction($action) public function beforeAction($action)
{ {
$requestMethod = Yii::$app->request->getRequestMethod(); $requestMethod = Yii::$app->request->getRequestMethod();
if ($requestMethod !== 'GET' && $requestMethod !== 'HEAD') { if ($requestMethod !== 'GET' && $requestMethod !== 'HEAD' || $this->lastModified === null && $this->etagSeed === null) {
return true; return true;
} }
...@@ -75,29 +76,36 @@ class HttpCache extends ActionFilter ...@@ -75,29 +76,36 @@ class HttpCache extends ActionFilter
$etag = $this->generateEtag($seed); $etag = $this->generateEtag($seed);
} }
$this->sendCacheControlHeader();
if ($etag !== null) { if ($etag !== null) {
header("ETag: $etag"); 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) { if ($lastModified !== null) {
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $lastModified) . ' GMT'); header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $lastModified) . ' GMT');
} }
return true; 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 ($lastModified !== null && (!isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) || @strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) < $lastModified)) {
if (!$changed && $etag !== null) { return false;
$changed = !isset($_SERVER['HTTP_IF_NONE_MATCH']) || $_SERVER['HTTP_IF_NONE_MATCH'] !== $etag; } 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 ...@@ -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 * @param string $seed Seed for the ETag
* @return string the generated Etag * @return string the generated Etag
*/ */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment