Skip to content

Commit

Permalink
Fixing Content-Length calculation when there is buffered output that …
Browse files Browse the repository at this point in the history
…will be sent before the response body. fixes #2208
  • Loading branch information
lorenzo committed Nov 4, 2011
1 parent 606c30b commit 2711178
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 7 deletions.
25 changes: 18 additions & 7 deletions lib/Cake/Network/CakeResponse.php
Expand Up @@ -349,19 +349,30 @@ public function send() {
$codeMessage = $this->_statusCodes[$this->_status]; $codeMessage = $this->_statusCodes[$this->_status];
$this->_sendHeader("{$this->_protocol} {$this->_status} {$codeMessage}"); $this->_sendHeader("{$this->_protocol} {$this->_status} {$codeMessage}");
$this->_sendHeader('Content-Type', "{$this->_contentType}; charset={$this->_charset}"); $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)); $shouldSetLength = empty($this->_headers['Content-Length']) && !in_array($this->_status, range(301, 307));
if ($shouldSetLength && !$this->outputCompressed()) { if ($shouldSetLength && !$this->outputCompressed()) {
$offset = ob_get_level() ? ob_get_length() : 0;
if (ini_get('mbstring.func_overload') & 2 && function_exists('mb_strlen')) { 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 { } 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. * Sends a header to the client.
Expand Down
17 changes: 17 additions & 0 deletions lib/Cake/Test/Case/Network/CakeResponseTest.php
Expand Up @@ -424,5 +424,22 @@ public function testSendContentLength() {
$response->expects($this->once())->method('_sendContent')->with($body); $response->expects($this->once())->method('_sendContent')->with($body);
$response->expects($this->exactly(2))->method('_sendHeader'); $response->expects($this->exactly(2))->method('_sendHeader');
$response->send(); $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();
} }
} }

0 comments on commit 2711178

Please sign in to comment.