From 090e85a5a489c6d43675a3eeb9a83cb9f0c6ec05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20W=C5=82adysz?= Date: Sat, 25 Oct 2014 19:49:56 +0200 Subject: [PATCH] Make CakeResponse::file() accept ranges even when download option is false. --- lib/Cake/Network/CakeResponse.php | 13 +- .../Test/Case/Network/CakeResponseTest.php | 162 ++++++++++++++++-- 2 files changed, 156 insertions(+), 19 deletions(-) diff --git a/lib/Cake/Network/CakeResponse.php b/lib/Cake/Network/CakeResponse.php index 05352908238..a7294adf451 100644 --- a/lib/Cake/Network/CakeResponse.php +++ b/lib/Cake/Network/CakeResponse.php @@ -1382,18 +1382,17 @@ public function file($path, $options = array()) { $name = $options['name']; } $this->download($name); - $this->header('Accept-Ranges', 'bytes'); $this->header('Content-Transfer-Encoding', 'binary'); + } - $httpRange = env('HTTP_RANGE'); - if (isset($httpRange)) { - $this->_fileRange($file, $httpRange); - } else { - $this->header('Content-Length', $fileSize); - } + $this->header('Accept-Ranges', 'bytes'); + $httpRange = env('HTTP_RANGE'); + if (isset($httpRange)) { + $this->_fileRange($file, $httpRange); } else { $this->header('Content-Length', $fileSize); } + $this->_clearBuffer(); $this->_file = $file; } diff --git a/lib/Cake/Test/Case/Network/CakeResponseTest.php b/lib/Cake/Test/Case/Network/CakeResponseTest.php index 6654f686f57..acd58cab538 100644 --- a/lib/Cake/Test/Case/Network/CakeResponseTest.php +++ b/lib/Cake/Test/Case/Network/CakeResponseTest.php @@ -1199,6 +1199,10 @@ public function testFile() { ->will($this->returnArgument(0)); $response->expects($this->at(1)) + ->method('header') + ->with('Accept-Ranges', 'bytes'); + + $response->expects($this->at(2)) ->method('header') ->with('Content-Length', 38); @@ -1249,11 +1253,11 @@ public function testFileWithUnknownFileTypeGeneric() { $response->expects($this->at(2)) ->method('header') - ->with('Accept-Ranges', 'bytes'); + ->with('Content-Transfer-Encoding', 'binary'); $response->expects($this->at(3)) ->method('header') - ->with('Content-Transfer-Encoding', 'binary'); + ->with('Accept-Ranges', 'bytes'); $response->expects($this->at(4)) ->method('header') @@ -1314,11 +1318,11 @@ public function testFileWithUnknownFileTypeOpera() { $response->expects($this->at(3)) ->method('header') - ->with('Accept-Ranges', 'bytes'); + ->with('Content-Transfer-Encoding', 'binary'); $response->expects($this->at(4)) ->method('header') - ->with('Content-Transfer-Encoding', 'binary'); + ->with('Accept-Ranges', 'bytes'); $response->expects($this->at(5)) ->method('header') @@ -1378,11 +1382,11 @@ public function testFileWithUnknownFileTypeIE() { $response->expects($this->at(3)) ->method('header') - ->with('Accept-Ranges', 'bytes'); + ->with('Content-Transfer-Encoding', 'binary'); $response->expects($this->at(4)) ->method('header') - ->with('Content-Transfer-Encoding', 'binary'); + ->with('Accept-Ranges', 'bytes'); $response->expects($this->at(5)) ->method('header') @@ -1432,6 +1436,10 @@ public function testFileWithUnknownFileNoDownload() { ->with('ini') ->will($this->returnValue(false)); + $response->expects($this->at(1)) + ->method('header') + ->with('Accept-Ranges', 'bytes'); + $response->expects($this->never()) ->method('download'); @@ -1584,11 +1592,11 @@ public function testFileRangeOffsets($range, $length, $offsetResponse) { $response->expects($this->at(2)) ->method('header') - ->with('Accept-Ranges', 'bytes'); + ->with('Content-Transfer-Encoding', 'binary'); $response->expects($this->at(3)) ->method('header') - ->with('Content-Transfer-Encoding', 'binary'); + ->with('Accept-Ranges', 'bytes'); $response->expects($this->at(4)) ->method('header') @@ -1639,11 +1647,11 @@ public function testFileRange() { $response->expects($this->at(2)) ->method('header') - ->with('Accept-Ranges', 'bytes'); + ->with('Content-Transfer-Encoding', 'binary'); $response->expects($this->at(3)) ->method('header') - ->with('Content-Transfer-Encoding', 'binary'); + ->with('Accept-Ranges', 'bytes'); $response->expects($this->at(4)) ->method('header') @@ -1694,11 +1702,11 @@ public function testFileRangeInvalid() { $response->expects($this->at(2)) ->method('header') - ->with('Accept-Ranges', 'bytes'); + ->with('Content-Transfer-Encoding', 'binary'); $response->expects($this->at(3)) ->method('header') - ->with('Content-Transfer-Encoding', 'binary'); + ->with('Accept-Ranges', 'bytes'); $response->expects($this->at(4)) ->method('header') @@ -1715,6 +1723,136 @@ public function testFileRangeInvalid() { $result = $response->send(); } +/** + * testFileRangeOffsetsNoDownload method + * + * @dataProvider rangeProvider + * @return void + */ + public function testFileRangeOffsetsNoDownload($range, $length, $offsetResponse) { + $_SERVER['HTTP_RANGE'] = $range; + $response = $this->getMock('CakeResponse', array( + 'header', + 'type', + '_sendHeader', + '_isActive', + '_clearBuffer', + '_flushBuffer' + )); + + $response->expects($this->at(1)) + ->method('header') + ->with('Accept-Ranges', 'bytes'); + + $response->expects($this->at(2)) + ->method('header') + ->with(array( + 'Content-Length' => $length, + 'Content-Range' => $offsetResponse, + )); + + $response->expects($this->any()) + ->method('_isActive') + ->will($this->returnValue(true)); + + $response->file( + CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'css' . DS . 'test_asset.css', + array('download' => false) + ); + + ob_start(); + $result = $response->send(); + ob_get_clean(); + } + +/** + * testFileRangeNoDownload method + * + * @return void + */ + public function testFileRangeNoDownload() { + $_SERVER['HTTP_RANGE'] = 'bytes=8-25'; + $response = $this->getMock('CakeResponse', array( + 'header', + 'type', + '_sendHeader', + '_setContentType', + '_isActive', + '_clearBuffer', + '_flushBuffer' + )); + + $response->expects($this->exactly(1)) + ->method('type') + ->with('css') + ->will($this->returnArgument(0)); + + $response->expects($this->at(1)) + ->method('header') + ->with('Accept-Ranges', 'bytes'); + + $response->expects($this->at(2)) + ->method('header') + ->with(array( + 'Content-Length' => 18, + 'Content-Range' => 'bytes 8-25/38', + )); + + $response->expects($this->once())->method('_clearBuffer'); + + $response->expects($this->any()) + ->method('_isActive') + ->will($this->returnValue(true)); + + $response->file( + CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'css' . DS . 'test_asset.css', + array('download' => false) + ); + + ob_start(); + $result = $response->send(); + $output = ob_get_clean(); + $this->assertEquals(206, $response->statusCode()); + $this->assertEquals("is the test asset ", $output); + $this->assertTrue($result !== false); + } + +/** + * testFileRangeInvalidNoDownload method + * + * @return void + */ + public function testFileRangeInvalidNoDownload() { + $_SERVER['HTTP_RANGE'] = 'bytes=30-2'; + $response = $this->getMock('CakeResponse', array( + 'header', + 'type', + '_sendHeader', + '_setContentType', + '_isActive', + '_clearBuffer', + '_flushBuffer' + )); + + $response->expects($this->at(1)) + ->method('header') + ->with('Accept-Ranges', 'bytes'); + + $response->expects($this->at(2)) + ->method('header') + ->with(array( + 'Content-Range' => 'bytes 0-37/38', + )); + + $response->file( + CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'css' . DS . 'test_asset.css', + array('download' => false) + ); + + $this->assertEquals(416, $response->statusCode()); + $result = $response->send(); + } + /** * Test the location method. *