BUG Setting response length directly before output (fixes #7574)

Complying to HTTP1.1/RFC2616 in terms of when to
set 'Content-Length' in the first place
This commit is contained in:
Ingo Schommer 2012-09-29 17:23:05 +02:00
parent b75c4b84ec
commit 356a367eb5
3 changed files with 21 additions and 3 deletions

View File

@ -141,6 +141,17 @@ class Director implements TemplateGlobalProvider {
number_format(memory_get_peak_usage(),0) number_format(memory_get_peak_usage(),0)
)); ));
} else { } else {
// Set content length (according to RFC2616)
if(
!headers_sent()
&& $response->getBody()
&& $req->httpMethod() != 'HEAD'
&& $response->getStatusCode() >= 200
&& !in_array($response->getStatusCode(), array(204, 304))
) {
$response->fixContentLength();
}
$response->output(); $response->output();
} }
} else { } else {

View File

@ -150,9 +150,6 @@ class SS_HTTPResponse {
public function setBody($body) { public function setBody($body) {
$this->body = $body; $this->body = $body;
// Set content-length in bytes. Use mbstring to avoid problems with mb_internal_encoding() and mbstring.func_overload
$this->headers['Content-Length'] = mb_strlen($this->body,'8bit');
} }
public function getBody() { public function getBody() {
@ -248,6 +245,14 @@ class SS_HTTPResponse {
public function isFinished() { public function isFinished() {
return in_array($this->statusCode, array(301, 302, 401, 403)); return in_array($this->statusCode, array(301, 302, 401, 403));
} }
/**
* Set content-length in bytes. Should be called right before {@link output()}.
*/
public function fixContentLength() {
// Use mbstring to avoid problems with mb_internal_encoding() and mbstring.func_overload
$this->headers['Content-Length'] = mb_strlen($this->body,'8bit');
}
} }

View File

@ -15,6 +15,7 @@ class HTTPResponseTest extends SapphireTest {
public function testContentLengthHeader() { public function testContentLengthHeader() {
$r = new SS_HTTPResponse('123ü'); $r = new SS_HTTPResponse('123ü');
$r->fixContentLength();
$this->assertNotNull($r->getHeader('Content-Length'), 'Content-length header is added'); $this->assertNotNull($r->getHeader('Content-Length'), 'Content-length header is added');
$this->assertEquals( $this->assertEquals(
5, 5,
@ -23,6 +24,7 @@ class HTTPResponseTest extends SapphireTest {
); );
$r->setBody('1234ü'); $r->setBody('1234ü');
$r->fixContentLength();
$this->assertEquals( $this->assertEquals(
6, 6,
$r->getHeader('Content-Length'), $r->getHeader('Content-Length'),