diff --git a/docs/book/response.md b/docs/book/response.md index e1413cc2..351bde44 100644 --- a/docs/book/response.md +++ b/docs/book/response.md @@ -138,3 +138,18 @@ $response->setContent(<< EOS); ``` + +### handle Headers already sent + +> Available since version 2.13.0 + +We can handle header already sent by pass callable via `Response::setHeadersSentHandler()`: + +```php +use Laminas\Http\Response; + +$response = new Response(); +$response->setHeadersSentHandler(function ($response): void { + throw new RuntimeException('Cannot send headers, headers already sent'); +}); +``` diff --git a/src/PhpEnvironment/Response.php b/src/PhpEnvironment/Response.php index cbfb3d6a..f5f20a55 100644 --- a/src/PhpEnvironment/Response.php +++ b/src/PhpEnvironment/Response.php @@ -8,6 +8,7 @@ namespace Laminas\Http\PhpEnvironment; +use Laminas\Http\Exception\InvalidArgumentException; use Laminas\Http\Header\MultipleHeaderInterface; use Laminas\Http\Response as HttpResponse; @@ -29,6 +30,11 @@ class Response extends HttpResponse */ protected $contentSent = false; + /** + * @var null|callable + */ + private $headersSentHandler; + /** * Return the HTTP version for this response * @@ -74,6 +80,14 @@ public function contentSent() return $this->contentSent; } + /** + * @return void + */ + public function setHeadersSentHandler(callable $handler) + { + $this->headersSentHandler = $handler; + } + /** * Send HTTP headers * @@ -82,6 +96,10 @@ public function contentSent() public function sendHeaders() { if ($this->headersSent()) { + if ($this->headersSentHandler) { + call_user_func($this->headersSentHandler, $this); + } + return $this; } diff --git a/test/PhpEnvironment/ResponseTest.php b/test/PhpEnvironment/ResponseTest.php index 59be8859..80c8c260 100644 --- a/test/PhpEnvironment/ResponseTest.php +++ b/test/PhpEnvironment/ResponseTest.php @@ -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; @@ -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(); + } }