From fd8971ba067f6efd43466c0d99638ec0c06bb8cc Mon Sep 17 00:00:00 2001 From: Jose Lorenzo Rodriguez Date: Thu, 19 Apr 2012 00:00:32 -0430 Subject: [PATCH] Adding smart header checking to return 304 response in AssetDispatcher filter --- lib/Cake/Routing/Filter/AssetDispatcher.php | 5 +- lib/Cake/Routing/Filter/CacheDispatcher.php | 1 + .../Routing/Filter/AssetDispatcherTest.php | 50 +++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/lib/Cake/Routing/Filter/AssetDispatcher.php b/lib/Cake/Routing/Filter/AssetDispatcher.php index f1be060f2..11840ba8b 100644 --- a/lib/Cake/Routing/Filter/AssetDispatcher.php +++ b/lib/Cake/Routing/Filter/AssetDispatcher.php @@ -80,7 +80,10 @@ class AssetDispatcher extends DispatcherFilter { if ($assetFile !== null) { $event->stopPropagation(); - $this->_deliverAsset($response, $assetFile, $ext); + $response->modified(filemtime($assetFile)); + if (!$response->checkNotModified($event->data['request'])) { + $this->_deliverAsset($response, $assetFile, $ext); + } return $response; } } diff --git a/lib/Cake/Routing/Filter/CacheDispatcher.php b/lib/Cake/Routing/Filter/CacheDispatcher.php index 65387cb53..271402fd5 100644 --- a/lib/Cake/Routing/Filter/CacheDispatcher.php +++ b/lib/Cake/Routing/Filter/CacheDispatcher.php @@ -61,6 +61,7 @@ class CacheDispatcher extends DispatcherFilter { $view = new View($controller); $result = $view->renderCache($filename, microtime(true)); if ($result !== false) { + $event->stopPropagation(); $event->data['response']->body($result); return $event->data['response']; } diff --git a/lib/Cake/Test/Case/Routing/Filter/AssetDispatcherTest.php b/lib/Cake/Test/Case/Routing/Filter/AssetDispatcherTest.php index 593619aa4..4df0a35ef 100644 --- a/lib/Cake/Test/Case/Routing/Filter/AssetDispatcherTest.php +++ b/lib/Cake/Test/Case/Routing/Filter/AssetDispatcherTest.php @@ -44,6 +44,10 @@ class AssetDispatcherTest extends CakeTestCase { 'js' => '', 'css' => '' )); + App::build(array( + 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS), + 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS) + ), APP::RESET); $request = new CakeRequest('theme/test_theme/ccss/cake.generic.css'); $event = new CakeEvent('DispatcherTest', $this, compact('request', 'response')); @@ -75,4 +79,50 @@ class AssetDispatcherTest extends CakeTestCase { $this->assertNull($filter->beforeDispatch($event)); $this->assertFalse($event->isStopped()); } + +/** + * Tests that $response->checkNotModified() is called and bypasses + * file dispatching + * + * @return void + **/ + public function testNotModified() { + $filter = new AssetDispatcher(); + Configure::write('Asset.filter', array( + 'js' => '', + 'css' => '' + )); + App::build(array( + 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS), + 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS) + )); + $time = filemtime(App::themePath('TestTheme') . 'webroot' . DS . 'img' . DS . 'cake.power.gif'); + $time = new DateTime(date('Y-m-d H:i:s', $time), new DateTimeZone('UTC')); + + $response = $this->getMock('CakeResponse', array('send', 'checkNotModified')); + $request = new CakeRequest('theme/test_theme/img/cake.power.gif'); + + $response->expects($this->once())->method('checkNotModified') + ->with($request) + ->will($this->returnValue(true)); + $event = new CakeEvent('DispatcherTest', $this, compact('request', 'response')); + + ob_start(); + $this->assertSame($response, $filter->beforeDispatch($event)); + ob_end_clean(); + $this->assertEquals(200, $response->statusCode()); + $this->assertEquals($time->format('D, j M Y H:i:s') . ' GMT', $response->modified()); + + $response = $this->getMock('CakeResponse', array('_sendHeader', 'checkNotModified')); + $request = new CakeRequest('theme/test_theme/img/cake.power.gif'); + + $response->expects($this->once())->method('checkNotModified') + ->with($request) + ->will($this->returnValue(true)); + $response->expects($this->never())->method('send'); + $event = new CakeEvent('DispatcherTest', $this, compact('request', 'response')); + + $this->assertSame($response, $filter->beforeDispatch($event)); + $this->assertEquals($time->format('D, j M Y H:i:s') . ' GMT', $response->modified()); + } } \ No newline at end of file