Fixing a couple bugs in CakeResponse::checkNotModified() and implementing conditional rendering in

RequestHandlerComponent
This commit is contained in:
Jose Lorenzo Rodriguez 2012-01-19 00:32:34 -04:30
parent 28ee27e2dd
commit 979f7a28b5
3 changed files with 79 additions and 2 deletions

View file

@ -95,7 +95,8 @@ class RequestHandlerComponent extends Component {
* @param array $settings Array of settings.
*/
public function __construct(ComponentCollection $collection, $settings = array()) {
parent::__construct($collection, $settings);
$default = array('checkHttpCache' => true);
parent::__construct($collection, $settings + $default);
$this->addInputType('xml', array(array($this, 'convertXml')));
$Controller = $collection->getController();
@ -240,6 +241,23 @@ class RequestHandlerComponent extends Component {
$this->_stop();
}
/**
* Checks if the response can be considered different according to the request
* headers, and the caching response headers. If it was not modified, then the
* render process is skipped. And the client will get a blank response with a
* "304 Not Modified" header.
*
* @params Controller $controller
* @return boolean false if the render process should be aborted
**/
public function beforeRender($controller) {
$shouldCheck = $this->settings['checkHttpCache'];
if ($shouldCheck && $this->response->checkNotModified($this->request)) {
$this->response->send();
return false;
}
}
/**
* Returns true if the current HTTP request is Ajax, false otherwise
*

View file

@ -1034,7 +1034,11 @@ class CakeResponse {
if ($modifiedSince) {
$timeMatches = strtotime($this->modified()) == strtotime($modifiedSince);
}
$notModified = (!isset($etagMatches) || $etagMatches) && (!isset($timeMatches) || $timeMatches);
$checks = compact('etagMatches', 'timeMatches');
if (empty($checks)) {
return false;
}
$notModified = !in_array(false, $checks, true);
if ($notModified) {
$this->notModified();
}

View file

@ -824,4 +824,59 @@ class RequestHandlerComponentTest extends CakeTestCase {
$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');
$this->assertFalse($RequestHandler->beforeRender($this->Controller));
}
/**
* 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->assertFalse($RequestHandler->beforeRender($this->Controller));
}
/**
* 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->assertFalse($RequestHandler->beforeRender($this->Controller));
}
/**
* Test checkNotModified method
*
* @return void
**/
public function testCheckNotModifiedNoInfo() {
$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->assertNull($RequestHandler->beforeRender($this->Controller));
}
}