Permalink
Browse files

Implementing RequestHandler::checkNotModified() as a helper for HTTP …

…caching
  • Loading branch information...
lorenzo committed Jan 13, 2012
1 parent 8e979cc commit dffe84cfbcd1d49dc334f40093484904c45e7779
@@ -704,4 +704,33 @@ public function addInputType($type, $handler) {
}
$this->_inputTypeMap[$type] = $handler;
}
+
+/**
+ * Checks whether a response has not been modified according to the 'If-None-Match'
+ * (Etags) and 'If-Modified-Since' (last modification date) request
+ * headers headers. If the response is detected to be not modified, it
+ * is marked as so accordingly so the client can be informed of that.
+ *
+ * In order to mark a response as not modified, you need to set at least
+ * the Last-Modified response header or a response etag to be compared
+ * with the request itself
+ *
+ * @return boolean whether the response was marked as not modified or
+ * not
+ **/
+ public function checkNotModified() {
+ $etags = preg_split('/\s*,\s*/', $this->request->header('If-None-Match'), null, PREG_SPLIT_NO_EMPTY);
+ $modifiedSince = $this->request->header('If-Modified-Since');
+ if ($responseTag = $this->response->etag()) {
+ $etagMatches = in_array('*', $etags) || in_array($responseTag, $etags);
+ }
+ if ($modifiedSince) {
+ $timeMatches = strtotime($this->response->modified()) == strtotime($modifiedSince);
+ }
+ $notModified = (!isset($etagMatches) || $etagMatches) && (!isset($timeMatches) || $timeMatches);
+ if ($notModified) {
+ $this->response->notModified();
+ }
+ return $notModified;
+ }
}
@@ -823,4 +823,109 @@ public function testBeforeRedirectCallingHeader() {
public function testAddInputTypeException() {
$this->RequestHandler->addInputType('csv', array('I am not callable'));
}
+
+/**
+ * Test checkNotModified method
+ *
+ * @return void
+ **/
+ public function testCheckNotModifiedByEtagStar() {
+ $_SERVER['HTTP_IF_NONE_MATCH'] = '*';
+ $RequestHandler = $this->getMock('RequestHandlerComponent', array('_stop'), array(&$this->Controller->Components));
+ $RequestHandler->response = $this->getMock('CakeResponse', array('notModified'));
+ $RequestHandler->response->etag('something');
+ $RequestHandler->response->expects($this->once())->method('notModified');
+ $RequestHandler->checkNotModified();
+ }
+
+/**
+ * Test checkNotModified method
+ *
+ * @return void
+ **/
+ public function testCheckNotModifiedByEtagExact() {
+ $_SERVER['HTTP_IF_NONE_MATCH'] = 'W/"something", "other"';
+ $RequestHandler = $this->getMock('RequestHandlerComponent', array('_stop'), array(&$this->Controller->Components));
+ $RequestHandler->response = $this->getMock('CakeResponse', array('notModified'));
+ $RequestHandler->response->etag('something', true);
+ $RequestHandler->response->expects($this->once())->method('notModified');
+ $this->assertTrue($RequestHandler->checkNotModified());
+ }
+
+/**
+ * Test checkNotModified method
+ *
+ * @return void
+ **/
+ public function testCheckNotModifiedByEtagAndTime() {
+ $_SERVER['HTTP_IF_NONE_MATCH'] = 'W/"something", "other"';
+ $_SERVER['HTTP_IF_MODIFIED_SINCE'] = '2012-01-01 00:00:00';
+ $RequestHandler = $this->getMock('RequestHandlerComponent', array('_stop'), array(&$this->Controller->Components));
+ $RequestHandler->response = $this->getMock('CakeResponse', array('notModified'));
+ $RequestHandler->response->etag('something', true);
+ $RequestHandler->response->modified('2012-01-01 00:00:00');
+ $RequestHandler->response->expects($this->once())->method('notModified');
+ $this->assertTrue($RequestHandler->checkNotModified());
+ }
+
+/**
+ * Test checkNotModified method
+ *
+ * @return void
+ **/
+ public function testCheckNotModifiedByEtagAndTimeMismatch() {
+ $_SERVER['HTTP_IF_NONE_MATCH'] = 'W/"something", "other"';
+ $_SERVER['HTTP_IF_MODIFIED_SINCE'] = '2012-01-01 00:00:00';
+ $RequestHandler = $this->getMock('RequestHandlerComponent', array('_stop'), array(&$this->Controller->Components));
+ $RequestHandler->response = $this->getMock('CakeResponse', array('notModified'));
+ $RequestHandler->response->etag('something', true);
+ $RequestHandler->response->modified('2012-01-01 00:00:01');
+ $RequestHandler->response->expects($this->never())->method('notModified');
+ $this->assertFalse($RequestHandler->checkNotModified());
+ }
+
+/**
+ * Test checkNotModified method
+ *
+ * @return void
+ **/
+ public function testCheckNotModifiedByEtagMismatch() {
+ $_SERVER['HTTP_IF_NONE_MATCH'] = 'W/"something-else", "other"';
+ $_SERVER['HTTP_IF_MODIFIED_SINCE'] = '2012-01-01 00:00:00';
+ $RequestHandler = $this->getMock('RequestHandlerComponent', array('_stop'), array(&$this->Controller->Components));
+ $RequestHandler->response = $this->getMock('CakeResponse', array('notModified'));
+ $RequestHandler->response->etag('something', true);
+ $RequestHandler->response->modified('2012-01-01 00:00:00');
+ $RequestHandler->response->expects($this->never())->method('notModified');
+ $this->assertFalse($RequestHandler->checkNotModified());
+ }
+
+
+/**
+ * Test checkNotModified method
+ *
+ * @return void
+ **/
+ public function testCheckNotModifiedByTime() {
+ $_SERVER['HTTP_IF_MODIFIED_SINCE'] = '2012-01-01 00:00:00';
+ $RequestHandler = $this->getMock('RequestHandlerComponent', array('_stop'), array(&$this->Controller->Components));
+ $RequestHandler->response = $this->getMock('CakeResponse', array('notModified'));
+ $RequestHandler->response->modified('2012-01-01 00:00:00');
+ $RequestHandler->response->expects($this->once())->method('notModified');
+ $this->assertTrue($RequestHandler->checkNotModified());
+ }
+
+ /**
+ * Test checkNotModified method
+ *
+ * @return void
+ **/
+ public function testCheckNotModifiedNoHints() {
+ $_SERVER['HTTP_IF_NONE_MATCH'] = 'W/"something", "other"';
+ $_SERVER['HTTP_IF_MODIFIED_SINCE'] = '2012-01-01 00:00:00';
+ $RequestHandler = $this->getMock('RequestHandlerComponent', array('_stop'), array(&$this->Controller->Components));
+ $RequestHandler->response = $this->getMock('CakeResponse', array('notModified'));
+ $RequestHandler->response->expects($this->never())->method('notModified');
+ $this->assertFalse($RequestHandler->checkNotModified());
+ }
}

0 comments on commit dffe84c

Please sign in to comment.