diff --git a/src/Transmission/Middleware/ContentLengthHandler.php b/src/Transmission/Middleware/ContentLengthHandler.php deleted file mode 100644 index 96579a6..0000000 --- a/src/Transmission/Middleware/ContentLengthHandler.php +++ /dev/null @@ -1,32 +0,0 @@ -hasHeader("Content-length")) { - return $next($request, $response); - } - if (strtolower($response->getHeaderLine("Transfer-encoding")) === "chunked") { - return $next($request, $response); - } - $size = $response->getBody()->getSize(); - if ($size !== null) { - $response = $response->withHeader("Content-length", (string) $size); - } - return $next($request, $response); - } -} diff --git a/src/Transmission/Middleware/HeadHandler.php b/src/Transmission/Middleware/HeadHandler.php deleted file mode 100644 index 5b18a96..0000000 --- a/src/Transmission/Middleware/HeadHandler.php +++ /dev/null @@ -1,25 +0,0 @@ -getMethod()); - if ($method === "HEAD") { - if ($response->getBody()->getSize() !== 0) { - $response = $response->withBody(new NullStream()); - } - } - return $next($request, $response); - } -} diff --git a/src/Transmission/Transmitter.php b/src/Transmission/Transmitter.php index 127c0b6..c3d0c34 100644 --- a/src/Transmission/Transmitter.php +++ b/src/Transmission/Transmitter.php @@ -7,8 +7,6 @@ use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\StreamInterface; use WellRESTed\Dispatching\Dispatcher; use WellRESTed\Dispatching\DispatcherInterface; -use WellRESTed\Transmission\Middleware\ContentLengthHandler; -use WellRESTed\Transmission\Middleware\HeadHandler; class Transmitter implements TransmitterInterface { @@ -31,8 +29,10 @@ class Transmitter implements TransmitterInterface * * This method outputs the status line, headers, and body to the client. * - * This method will also provide a Content-length header if needed and - * supress the body for HEAD requests. + * This method will also provide a Content-length header if: + * - Response does not have a Content-length header + * - Response does not have a Tranfser-encoding: chunked header + * - Response body stream is readable and reports a non-null size * * @param ServerRequestInterface $request * @param ResponseInterface $response Response to output @@ -69,17 +69,21 @@ class Transmitter implements TransmitterInterface protected function prepareResponse(ServerRequestInterface $request, ResponseInterface $response) { - return $this->dispatcher->dispatch( - [ - new ContentLengthHandler(), - new HeadHandler() - ], - $request, - $response, - function ($request, $response) { - return $response; + // Add a Content-length header to the response when all of these are true: + // + // - Response does not have a Content-length header + // - Response does not have a Tranfser-encoding: chunked header + // - Response body stream is readable and reports a non-null size + // + if (!$response->hasHeader("Content-length") + && !(strtolower($response->getHeaderLine("Transfer-encoding")) === "chunked") + ) { + $size = $response->getBody()->getSize(); + if ($size !== null) { + $response = $response->withHeader("Content-length", (string) $size); } - ); + } + return $response; } private function getStatusLine(ResponseInterface $response) diff --git a/src/Transmission/TransmitterInterface.php b/src/Transmission/TransmitterInterface.php index b68a691..4a639dd 100644 --- a/src/Transmission/TransmitterInterface.php +++ b/src/Transmission/TransmitterInterface.php @@ -12,9 +12,6 @@ interface TransmitterInterface * * This method MUST output the status line, headers, and body to the client. * - * This method MUST NOT alter the response body, unless it is to remove the - * body for a HEAD request. - * * Implementations MAY add response headers to ensure expected headers are * presents but MUST NOT alter existing headers. * diff --git a/test/tests/unit/Transmission/Middleware/ContentLengthHookTest.php b/test/tests/unit/Transmission/Middleware/ContentLengthHookTest.php deleted file mode 100644 index 6abe908..0000000 --- a/test/tests/unit/Transmission/Middleware/ContentLengthHookTest.php +++ /dev/null @@ -1,98 +0,0 @@ -body = $this->prophesize('Psr\Http\Message\StreamInterface'); - $this->body->getSize()->willReturn(1024); - $this->request = $this->prophesize('Psr\Http\Message\ServerRequestInterface'); - $this->response = $this->prophesize('Psr\Http\Message\ResponseInterface'); - $this->response->getBody()->willReturn($this->body->reveal()); - $this->response->withHeader(Argument::cetera())->will( - function ($args) { - $this->hasHeader($args[0])->willReturn(true); - $this->getHeader($args[0])->willReturn([$args[1]]); - $this->getHeaderLine($args[0])->willReturn($args[1]); - return $this; - } - ); - $this->next = function ($request, $response) { - return $response; - }; - } - - public function testAddsContentLengthHeader() - { - $this->response->hasHeader("Content-length")->willReturn(false); - $this->response->getHeaderLine("Transfer-encoding")->willReturn(""); - - $hook = new ContentLengthHandler(); - $response = $hook->dispatch($this->request->reveal(), $this->response->reveal(), $this->next); - - $this->assertEquals([1024], $response->getHeader("Content-length")); - } - - public function testMultipleDispatchesHaveNoEffect() - { - $this->response->hasHeader("Content-length")->willReturn(false); - $this->response->getHeaderLine("Transfer-encoding")->willReturn(""); - - $hook = new ContentLengthHandler(); - - $response = $this->response->reveal(); - $response = $hook->dispatch($this->request->reveal(), $response, $this->next); - $hook->dispatch($this->request->reveal(), $response, $this->next); - - $this->response->withHeader("Content-length", 1024)->shouldHaveBeenCalledTimes(1); - } - - public function testDoesNotAddHeaderWhenContentLenghtIsAlreadySet() - { - $this->response->hasHeader("Content-length")->willReturn(true); - $this->response->getHeaderLine("Transfer-encoding")->willReturn(""); - - $hook = new ContentLengthHandler(); - $hook->dispatch($this->request->reveal(), $this->response->reveal(), $this->next); - - $this->response->withHeader(Argument::cetera())->shouldNotHaveBeenCalled(); - } - - public function testDoesNotAddHeaderWhenTransferEncodingIsChunked() - { - $this->response->hasHeader("Content-length")->willReturn(false); - $this->response->getHeaderLine("Transfer-encoding")->willReturn("CHUNKED"); - - $hook = new ContentLengthHandler(); - $hook->dispatch($this->request->reveal(), $this->response->reveal(), $this->next); - - $this->response->withHeader(Argument::cetera())->shouldNotHaveBeenCalled(); - } - - public function testDoesNotAddHeaderWhenBodySizeIsNull() - { - $this->response->hasHeader("Content-length")->willReturn(false); - $this->response->getHeaderLine("Transfer-encoding")->willReturn(""); - $this->body->getSize()->willReturn(null); - - $hook = new ContentLengthHandler(); - $hook->dispatch($this->request->reveal(), $this->response->reveal(), $this->next); - - $this->response->withHeader(Argument::cetera())->shouldNotHaveBeenCalled(); - } -} diff --git a/test/tests/unit/Transmission/Middleware/HeadHandlerTest.php b/test/tests/unit/Transmission/Middleware/HeadHandlerTest.php deleted file mode 100644 index 0f30ee6..0000000 --- a/test/tests/unit/Transmission/Middleware/HeadHandlerTest.php +++ /dev/null @@ -1,63 +0,0 @@ -body = $this->prophesize('Psr\Http\Message\StreamInterface'); - $this->body->getSize()->willReturn(1024); - $this->request = $this->prophesize('Psr\Http\Message\ServerRequestInterface'); - $this->response = $this->prophesize('Psr\Http\Message\ResponseInterface'); - $this->response->getBody()->willReturn($this->body->reveal()); - $this->response->withBody(Argument::any())->will( - function ($args) { - $this->getBody()->willReturn($args[0]); - return $this; - } - ); - $this->next = function ($request, $response) { - return $response; - }; - } - - public function testReplacesBodyForHeadRequest() - { - $this->request->getMethod()->willReturn("HEAD"); - $hook = new HeadHandler(); - $response = $hook->dispatch($this->request->reveal(), $this->response->reveal(), $this->next); - $this->assertSame(0, $response->getBody()->getSize()); - } - - public function testMultipleDispatchesHaveNoEffect() - { - $this->request->getMethod()->willReturn("HEAD"); - $hook = new HeadHandler(); - $response = $hook->dispatch($this->request->reveal(), $this->response->reveal(), $this->next); - $hook->dispatch($this->request->reveal(), $response, $this->next); - $this->response->withBody(Argument::any())->shouldHaveBeenCalledTimes(1); - } - - public function testDoesNotReplaceBodyForNonHeadRequests() - { - $this->request->getMethod()->willReturn("GET"); - $hook = new HeadHandler(); - $hook->dispatch($this->request->reveal(), $this->response->reveal(), $this->next); - $this->response->withBody(Argument::any())->shouldNotHaveBeenCalled(); - } -} diff --git a/test/tests/unit/Transmission/TransmitterTest.php b/test/tests/unit/Transmission/TransmitterTest.php index f94d54b..3aecc21 100644 --- a/test/tests/unit/Transmission/TransmitterTest.php +++ b/test/tests/unit/Transmission/TransmitterTest.php @@ -11,8 +11,6 @@ require_once __DIR__ . "/../../../src/HeaderStack.php"; /** * @coversDefaultClass WellRESTed\Transmission\Transmitter * @uses WellRESTed\Transmission\Transmitter - * @uses WellRESTed\Transmission\Middleware\ContentLengthHandler - * @uses WellRESTed\Transmission\Middleware\HeadHandler * @uses WellRESTed\Dispatching\Dispatcher * @uses WellRESTed\Dispatching\DispatchStack * @group transmission @@ -163,6 +161,9 @@ class TransmitterTest extends \PHPUnit_Framework_TestCase $this->assertEquals($content, $captured); } + // ------------------------------------------------------------------------ + // Preparation + /** * @covers ::prepareResponse */ @@ -184,16 +185,55 @@ class TransmitterTest extends \PHPUnit_Framework_TestCase /** * @covers ::prepareResponse */ - public function testReplacesBodyForHeadRequeset() + public function testDoesNotReplaceContentLengthHeaderWhenContentLenghtIsAlreadySet() + { + $bodySize = 1024; + $this->response->getStatusCode()->willReturn("200"); + $this->response->getReasonPhrase()->willReturn("Ok"); + $this->response->hasHeader("Content-length")->willReturn(true); + $this->body->isReadable()->willReturn(true); + $this->body->__toString()->willReturn(""); + $this->body->getSize()->willReturn($bodySize); + + $transmitter = new Transmitter(); + $transmitter->transmit($this->request->reveal(), $this->response->reveal()); + $this->response->withHeader("Content-length", $bodySize)->shouldNotHaveBeenCalled(); + } + + /** + * @covers ::prepareResponse + */ + public function testDoesNotAddContentLengthHeaderWhenTransferEncodingIsChunked() + { + $bodySize = 1024; + $this->response->getStatusCode()->willReturn("200"); + $this->response->getReasonPhrase()->willReturn("Ok"); + $this->response->hasHeader("Content-length")->willReturn(false); + $this->response->getHeaderLine("Transfer-encoding")->willReturn("CHUNKED"); + $this->body->isReadable()->willReturn(true); + $this->body->__toString()->willReturn(""); + $this->body->getSize()->willReturn($bodySize); + + $transmitter = new Transmitter(); + $transmitter->transmit($this->request->reveal(), $this->response->reveal()); + $this->response->withHeader("Content-length", $bodySize)->shouldNotHaveBeenCalled(); + } + + /** + * @covers ::prepareResponse + */ + public function testDoesNotAddContentLengthHeaderWhenBodySizeIsNull() { $this->response->getStatusCode()->willReturn("200"); $this->response->getReasonPhrase()->willReturn("Ok"); $this->response->hasHeader("Content-length")->willReturn(false); + $this->response->getHeaderLine("Transfer-encoding")->willReturn(""); $this->body->isReadable()->willReturn(true); $this->body->__toString()->willReturn(""); + $this->body->getSize()->willReturn(null); $transmitter = new Transmitter(); $transmitter->transmit($this->request->reveal(), $this->response->reveal()); - $this->response->withBody(Argument::any())->shouldHaveBeenCalled(); + $this->response->withHeader("Content-length", Argument::any())->shouldNotHaveBeenCalled(); } }