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

Extract extra info from headers_sent #13

Open
wants to merge 19 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/Emitter/SapiEmitterTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ trait SapiEmitterTrait
*/
private function assertNoPreviousOutput()
{
if (headers_sent()) {
throw EmitterException::forHeadersSent();
$file = null;
$line = null;
if (headers_sent($file, $line)) {
throw EmitterException::forHeadersSent($file, $line);
}

if (ob_get_level() > 0 && ob_get_length() > 0) {
Expand Down
10 changes: 8 additions & 2 deletions src/Exception/EmitterException.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,15 @@

class EmitterException extends RuntimeException implements ExceptionInterface
{
public static function forHeadersSent() : self
public static function forHeadersSent(string $file, int $line) : self
{
return new self('Unable to emit response; headers already sent');
return new self(
sprintf(
'Unable to emit response; headers already sent, output started at %s:%d',
$file,
$line
)
);
}

public static function forOutputSent() : self
Expand Down
20 changes: 20 additions & 0 deletions test/Emitter/SapiStreamEmitterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,26 @@ public function testEmitCallbackStreamResponse()
$this->assertSame('it works', ob_get_clean());
}

public function testAssertNoPreviousOutput()
{
$stream = new CallbackStream(function () {
return 'it works';
});
$response = (new Response())
->withStatus(200)
->withBody($stream);
ob_start();
echo 'Unexpected Output';
try {
$this->emitter->emit($response);
} catch (Exception $e) {
$this->assertTrue($e instanceof EmitterException);
$this->assertEquals('',$e->getMessage());
} finally {
ob_get_clean();
}
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try it like this:

$this->expectException(EmitterException::class);
$this->expectExceptionMessage('Unable to emit response; headers already sent');
$this->expectExceptionMessage(sprintf(
    'output started at %s:%d',
     __FILE__,
     __LINE__ + 3
));
ob_start();
echo 'Unexpected Output';
try {
    $this->emitter->emit($response);
} catch (\Throwable $e) {
    throw $e;
} finally {
    ob_end_clean();
}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, unsuccessfully ... I assume that sending headers is not called in the SAPI environment of tests, all my attempts at tests are unsuccessful ...

public function testDoesNotInjectContentLengthHeaderIfStreamSizeIsUnknown()
{
$stream = $this->prophesize(StreamInterface::class);
Expand Down