Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #5 : Handle Response::sendHeaders() to not silently returns when header already sent #41

Merged
merged 9 commits into from
Aug 18, 2020
13 changes: 13 additions & 0 deletions docs/book/response.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,16 @@ $response->setContent(<<<EOS
</html>
EOS);
```

### handle Headers already sent

Since 2.13.0, we can handle header already sent by pass callable via `Response::setHeadersSentHandler()`:
samsonasik marked this conversation as resolved.
Show resolved Hide resolved

```php
use Laminas\Http\Response;

$response = new Response();
$response->setHeadersSentHandler(function ($response): void {
throw new RuntimeException('Cannot send headers, headers already sent');
});
```
18 changes: 18 additions & 0 deletions src/PhpEnvironment/Response.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

namespace Laminas\Http\PhpEnvironment;

use Laminas\Http\Exception\InvalidArgumentException;
use Laminas\Http\Header\MultipleHeaderInterface;
use Laminas\Http\Response as HttpResponse;

Expand All @@ -29,6 +30,11 @@ class Response extends HttpResponse
*/
protected $contentSent = false;

/**
* @var null|callable
*/
private $headersSentHandler;

/**
* Return the HTTP version for this response
*
Expand Down Expand Up @@ -74,6 +80,14 @@ public function contentSent()
return $this->contentSent;
}

/**
* @return void
*/
public function setHeadersSentHandler(callable $handler)
{
$this->headersSentHandler = $handler;
}

/**
* Send HTTP headers
*
Expand All @@ -82,6 +96,10 @@ public function contentSent()
public function sendHeaders()
{
if ($this->headersSent()) {
if ($this->headersSentHandler) {
call_user_func($this->headersSentHandler, $this);
}

return $this;
}

Expand Down
23 changes: 23 additions & 0 deletions test/PhpEnvironment/ResponseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
namespace LaminasTest\Http\PhpEnvironment;

use Laminas\Http\Exception\InvalidArgumentException;
use Laminas\Http\Exception\RuntimeException;
use Laminas\Http\PhpEnvironment\Response;
use PHPUnit\Framework\TestCase;

Expand Down Expand Up @@ -100,4 +101,26 @@ public function testCanExplicitlySetVersion()
$this->expectException(InvalidArgumentException::class);
$response->setVersion('laminas/2.0');
}

/**
* @runInSeparateProcess
*/
public function testSendHeadersHeadersNotAlreadySent()
{
$response = new Response();
$this->assertInstanceOf(Response::class, $response->sendHeaders());
}

public function testSendHeadersHeadersAlreadySentPassValidHandler()
{
$response = new Response();
$response->setHeadersSentHandler(function ($response) {
throw new RuntimeException('Cannot send headers, headers already sent');
});

$this->expectException(RuntimeException::class);
$this->expectExceptionMessage('Cannot send headers, headers already sent');

$response->sendHeaders();
}
}