diff --git a/lib/Cake/Network/CakeResponse.php b/lib/Cake/Network/CakeResponse.php index 9607d160e..e7e3eb5c7 100644 --- a/lib/Cake/Network/CakeResponse.php +++ b/lib/Cake/Network/CakeResponse.php @@ -444,10 +444,20 @@ class CakeResponse { if (in_array($this->_status, array(304, 204))) { return; } - if (strpos($this->_contentType, 'text/') === 0) { + $whitelist = array( + 'application/javascript', 'application/json', 'application/xml', 'application/rss+xml' + ); + + $charset = false; + if ( + $this->_charset && + (strpos($this->_contentType, 'text/') === 0 || in_array($this->_contentType, $whitelist)) + ) { + $charset = true; + } + + if ($charset) { $this->header('Content-Type', "{$this->_contentType}; charset={$this->_charset}"); - } elseif ($this->_contentType === 'application/json') { - $this->header('Content-Type', "{$this->_contentType}; charset=UTF-8"); } else { $this->header('Content-Type', "{$this->_contentType}"); } diff --git a/lib/Cake/Test/Case/Network/CakeResponseTest.php b/lib/Cake/Test/Case/Network/CakeResponseTest.php index b373d158f..c8e06397c 100644 --- a/lib/Cake/Test/Case/Network/CakeResponseTest.php +++ b/lib/Cake/Test/Case/Network/CakeResponseTest.php @@ -196,12 +196,27 @@ class CakeResponseTest extends CakeTestCase { } /** - * Tests the send method and changing the content type + * Data provider for content type tests. * + * @return array */ - public function testSendChangingContentType() { + public static function charsetTypeProvider() { + return array( + array('mp3', 'audio/mpeg'), + array('js', 'application/javascript; charset=UTF-8'), + array('json', 'application/json; charset=UTF-8'), + array('xml', 'application/xml; charset=UTF-8'), + array('txt', 'text/plain; charset=UTF-8'), + ); + } + +/** + * Tests the send method and changing the content type + * @dataProvider charsetTypeProvider + */ + public function testSendChangingContentType($original, $expected) { $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent', '_setCookies')); - $response->type('mp3'); + $response->type($original); $response->body('the response body'); $response->expects($this->once())->method('_sendContent')->with('the response body'); $response->expects($this->at(0))->method('_setCookies'); @@ -210,26 +225,28 @@ class CakeResponseTest extends CakeTestCase { $response->expects($this->at(2)) ->method('_sendHeader')->with('Content-Length', 17); $response->expects($this->at(3)) - ->method('_sendHeader')->with('Content-Type', 'audio/mpeg'); + ->method('_sendHeader')->with('Content-Type', $expected); $response->send(); } /** - * Tests the send method and changing the content type to JSON + * Tests the send method and changing the content type to JS without adding the charset * */ - public function testSendChangingContentTypeJSON() { + public function testSendChangingContentTypeWithoutCharset() { $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent', '_setCookies')); - $response->type('json'); - $response->body('the response body'); - $response->expects($this->once())->method('_sendContent')->with('the response body'); + $response->type('js'); + $response->charset(''); + + $response->body('var $foo = "bar";'); + $response->expects($this->once())->method('_sendContent')->with('var $foo = "bar";'); $response->expects($this->at(0))->method('_setCookies'); $response->expects($this->at(1)) ->method('_sendHeader')->with('HTTP/1.1 200 OK'); $response->expects($this->at(2)) ->method('_sendHeader')->with('Content-Length', 17); $response->expects($this->at(3)) - ->method('_sendHeader')->with('Content-Type', 'application/json; charset=UTF-8'); + ->method('_sendHeader')->with('Content-Type', 'application/javascript'); $response->send(); }