diff --git a/lib/Cake/Network/CakeResponse.php b/lib/Cake/Network/CakeResponse.php index 473fd8026..6209b3b4e 100644 --- a/lib/Cake/Network/CakeResponse.php +++ b/lib/Cake/Network/CakeResponse.php @@ -349,20 +349,31 @@ class CakeResponse { $codeMessage = $this->_statusCodes[$this->_status]; $this->_sendHeader("{$this->_protocol} {$this->_status} {$codeMessage}"); $this->_sendHeader('Content-Type', "{$this->_contentType}; charset={$this->_charset}"); - $shouldSetLength = empty($this->_headers['Content-Length']) && !in_array($this->_status, range(301, 307)); - if ($shouldSetLength && !$this->outputCompressed()) { - if (ini_get('mbstring.func_overload') & 2 && function_exists('mb_strlen')) { - $this->_headers['Content-Length'] = mb_strlen($this->_body, '8bit'); - } else { - $this->_headers['Content-Length'] = strlen($this->_body); - } - } + $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'] = $offset + mb_strlen($this->_body, '8bit'); + } else { + $this->_headers['Content-Length'] = $offset + strlen($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 74b29573e..af85f95ca 100644 --- a/lib/Cake/Test/Case/Network/CakeResponseTest.php +++ b/lib/Cake/Test/Case/Network/CakeResponseTest.php @@ -424,5 +424,22 @@ class CakeResponseTest extends CakeTestCase { $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(); } }