Skip to content
This repository has been archived by the owner on Jan 29, 2020. It is now read-only.

Commit

Permalink
Removes Content-Length injection from SAPI stream emitters
Browse files Browse the repository at this point in the history
Per #251, this patch removes Content-Length injection from SAPI stream
emitters. It also renames the `checkForPreviousOutput()` method to
`assertNoPreviousOutput()` to make it more clear that the method is a
no-op under proper usage.

The `assertNoPreviousOutput()` method also borrows an idea from the
comment to the issue, indicating we can check for (1) a non-zero output
buffer, and (2) use `ob_get_length()` to determine if it has content.
  • Loading branch information
weierophinney committed Sep 11, 2017
1 parent ba5b16e commit 191699a
Show file tree
Hide file tree
Showing 5 changed files with 8 additions and 34 deletions.
4 changes: 1 addition & 3 deletions src/Response/SapiEmitter.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,7 @@ class SapiEmitter implements EmitterInterface
*/
public function emit(ResponseInterface $response)
{
$this->checkForPreviousOutput();

$response = $this->injectContentLength($response);
$this->assertNoPreviousOutput();

$this->emitStatusLine($response);
$this->emitHeaders($response);
Expand Down
31 changes: 6 additions & 25 deletions src/Response/SapiEmitterTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,40 +17,21 @@ trait SapiEmitterTrait
/**
* Checks to see if content has previously been sent.
*
* If either headers have been sent, or the current output buffer contains
* content, raises an exception.
* If either headers have been sent or the output buffer contains content,
* raises an exception.
*
* @throws RuntimeException if headers have already been sent.
* @throws RuntimeException if the current output buffer is not empty.
* @throws RuntimeException if output is present in the output buffer.
*/
private function checkForPreviousOutput()
private function assertNoPreviousOutput()
{
if (headers_sent()) {
throw new RuntimeException('Unable to emit response; headers already sent');
}
$bufferContents = ob_get_contents();
if (! empty($bufferContents)) {
throw new RuntimeException('Output has been emitted previously; cannot emit response: ' . $bufferContents);
}
}

/**
* Inject the Content-Length header if is not already present.
*
* @param ResponseInterface $response
* @return ResponseInterface
*/
private function injectContentLength(ResponseInterface $response)
{
if (! $response->hasHeader('Content-Length')) {
// PSR-7 indicates int OR null for the stream size; for null values,
// we will not auto-inject the Content-Length.
if (null !== $response->getBody()->getSize()) {
return $response->withHeader('Content-Length', (string) $response->getBody()->getSize());
}
if (ob_get_level() > 0 && ob_get_length() > 0) {
throw new RuntimeException('Output has been emitted previously; cannot emit response: ' . $bufferContents);
}

return $response;
}

/**
Expand Down
5 changes: 1 addition & 4 deletions src/Response/SapiStreamEmitter.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,7 @@ class SapiStreamEmitter implements EmitterInterface
*/
public function emit(ResponseInterface $response, $maxBufferLength = 8192)
{
$this->checkForPreviousOutput();

$response = $this->injectContentLength($response);

$this->assertNoPreviousOutput();
$this->emitStatusLine($response);
$this->emitHeaders($response);

Expand Down
1 change: 0 additions & 1 deletion test/Response/AbstractEmitterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ public function testEmitsResponseHeaders()
ob_end_clean();
$this->assertContains('HTTP/1.1 200 OK', HeaderStack::stack());
$this->assertContains('Content-Type: text/plain', HeaderStack::stack());
$this->assertContains('Content-Length: 8', HeaderStack::stack());
}

public function testEmitsMessageBody()
Expand Down
1 change: 0 additions & 1 deletion test/ServerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,6 @@ public function testEmitsHeadersWithMultipleValuesMultipleTimes()
*/
public function testHeaderOrderIsHonoredWhenEmitted($stack)
{
array_pop($stack); // ignore "Content-Length" automatically set by the response emitter
$header = array_pop($stack);
$this->assertContains(
'Set-Cookie: bar=baz; expires=Wed, 8 Oct 2014 10:30; path=/foo/bar; domain=example.com',
Expand Down

0 comments on commit 191699a

Please sign in to comment.