diff --git a/lib/Cake/Network/CakeResponse.php b/lib/Cake/Network/CakeResponse.php index 473fd8026f8..6209b3b4ec3 100644 --- a/lib/Cake/Network/CakeResponse.php +++ b/lib/Cake/Network/CakeResponse.php @@ -349,19 +349,30 @@ public function send() { $codeMessage = $this->_statusCodes[$this->_status]; $this->_sendHeader("{$this->_protocol} {$this->_status} {$codeMessage}"); $this->_sendHeader('Content-Type', "{$this->_contentType}; charset={$this->_charset}"); + $this->_setContentLength(); + foreach ($this->_headers as $header => $value) { + $this->_sendHeader($header, $value); + } + $this->_sendContent($this->_body); + } + +/** + * Calculates the correct Content-Length and sets it as a header in the response + * Will not set the value if already set or if the output is compressed. + * + * @return void + */ + protected function _setContentLength() { $shouldSetLength = empty($this->_headers['Content-Length']) && !in_array($this->_status, range(301, 307)); if ($shouldSetLength && !$this->outputCompressed()) { + $offset = ob_get_level() ? ob_get_length() : 0; if (ini_get('mbstring.func_overload') & 2 && function_exists('mb_strlen')) { - $this->_headers['Content-Length'] = mb_strlen($this->_body, '8bit'); + $this->_headers['Content-Length'] = $offset + mb_strlen($this->_body, '8bit'); } else { - $this->_headers['Content-Length'] = strlen($this->_body); + $this->_headers['Content-Length'] = $offset + strlen($this->_body); } } - foreach ($this->_headers as $header => $value) { - $this->_sendHeader($header, $value); - } - $this->_sendContent($this->_body); - } + } /** * Sends a header to the client. diff --git a/lib/Cake/Test/Case/Network/CakeResponseTest.php b/lib/Cake/Test/Case/Network/CakeResponseTest.php index 74b29573e68..af85f95ca59 100644 --- a/lib/Cake/Test/Case/Network/CakeResponseTest.php +++ b/lib/Cake/Test/Case/Network/CakeResponseTest.php @@ -424,5 +424,22 @@ public function testSendContentLength() { $response->expects($this->once())->method('_sendContent')->with($body); $response->expects($this->exactly(2))->method('_sendHeader'); $response->send(); + + ob_start(); + $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent')); + $goofyOutput = 'I am goofily sending output in the controller'; + echo $goofyOutput; + $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent')); + $body = '長い長い長いSubjectの場合はfoldingするのが正しいんだけどいったいどうなるんだろう?'; + $response->body($body); + $response->expects($this->once())->method('_sendContent')->with($body); + $response->expects($this->at(0)) + ->method('_sendHeader')->with('HTTP/1.1 200 OK'); + $response->expects($this->at(1)) + ->method('_sendHeader')->with('Content-Type', 'text/html; charset=UTF-8'); + $response->expects($this->at(2)) + ->method('_sendHeader')->with('Content-Length', strlen($goofyOutput) + 116); + $response->send(); + ob_end_clean(); } }