Skip to content

Commit

Permalink
Moving checkModified() to CakeResponse, having it in the RequestHandl…
Browse files Browse the repository at this point in the history
…er has too restrivtive
  • Loading branch information
lorenzo committed Jan 19, 2012
1 parent 6839f0c commit b79e0ad
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 132 deletions.
28 changes: 0 additions & 28 deletions lib/Cake/Controller/Component/RequestHandlerComponent.php
Expand Up @@ -705,32 +705,4 @@ 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;
}
}
29 changes: 29 additions & 0 deletions lib/Cake/Network/CakeResponse.php
Expand Up @@ -1012,6 +1012,35 @@ public function length($bytes = null) {
return null;
}

/**
* 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(CakeRequest $request) {
$etags = preg_split('/\s*,\s*/', $request->header('If-None-Match'), null, PREG_SPLIT_NO_EMPTY);
$modifiedSince = $request->header('If-Modified-Since');
if ($responseTag = $this->etag()) {
$etagMatches = in_array('*', $etags) || in_array($responseTag, $etags);
}
if ($modifiedSince) {
$timeMatches = strtotime($this->modified()) == strtotime($modifiedSince);
}
$notModified = (!isset($etagMatches) || $etagMatches) && (!isset($timeMatches) || $timeMatches);
if ($notModified) {
$this->notModified();
}
return $notModified;
}

/**
* String conversion. Fetches the response body as a string.
* Does *not* send headers.
Expand Down
Expand Up @@ -824,108 +824,4 @@ 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());
}
}
98 changes: 98 additions & 0 deletions lib/Cake/Test/Case/Network/CakeResponseTest.php
Expand Up @@ -17,6 +17,7 @@
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
App::uses('CakeResponse', 'Network');
App::uses('CakeRequest', 'Network');

class CakeResponseTest extends CakeTestCase {

Expand Down Expand Up @@ -823,4 +824,101 @@ public function testNotModified() {
$this->assertEquals(304, $response->statusCode());
}

/**
* Test checkNotModified method
*
* @return void
**/
public function testCheckNotModifiedByEtagStar() {
$_SERVER['HTTP_IF_NONE_MATCH'] = '*';
$response = $this->getMock('CakeResponse', array('notModified'));
$response->etag('something');
$response->expects($this->once())->method('notModified');
$response->checkNotModified(new CakeRequest);
}

/**
* Test checkNotModified method
*
* @return void
**/
public function testCheckNotModifiedByEtagExact() {
$_SERVER['HTTP_IF_NONE_MATCH'] = 'W/"something", "other"';
$response = $this->getMock('CakeResponse', array('notModified'));
$response->etag('something', true);
$response->expects($this->once())->method('notModified');
$this->assertTrue($response->checkNotModified(new CakeRequest));
}

/**
* 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';
$response = $this->getMock('CakeResponse', array('notModified'));
$response->etag('something', true);
$response->modified('2012-01-01 00:00:00');
$response->expects($this->once())->method('notModified');
$this->assertTrue($response->checkNotModified(new CakeRequest));
}

/**
* 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';
$response = $this->getMock('CakeResponse', array('notModified'));
$response->etag('something', true);
$response->modified('2012-01-01 00:00:01');
$response->expects($this->never())->method('notModified');
$this->assertFalse($response->checkNotModified(new CakeRequest));
}

/**
* 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';
$response = $this->getMock('CakeResponse', array('notModified'));
$response->etag('something', true);
$response->modified('2012-01-01 00:00:00');
$response->expects($this->never())->method('notModified');
$this->assertFalse($response->checkNotModified(new CakeRequest));
}


/**
* Test checkNotModified method
*
* @return void
**/
public function testCheckNotModifiedByTime() {
$_SERVER['HTTP_IF_MODIFIED_SINCE'] = '2012-01-01 00:00:00';
$response = $this->getMock('CakeResponse', array('notModified'));
$response->modified('2012-01-01 00:00:00');
$response->expects($this->once())->method('notModified');
$this->assertTrue($response->checkNotModified(new CakeRequest));
}

/**
* 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';
$response = $this->getMock('CakeResponse', array('notModified'));
$response->expects($this->never())->method('notModified');
$this->assertFalse($response->checkNotModified(new CakeRequest));
}
}

0 comments on commit b79e0ad

Please sign in to comment.