diff --git a/doc/book/custom-responses.md b/doc/book/custom-responses.md index 0d45a078..d9d855ac 100644 --- a/doc/book/custom-responses.md +++ b/doc/book/custom-responses.md @@ -23,6 +23,21 @@ Some standard use cases, however, make this un-wieldy: Starting with version 1.1, Diactoros offers several custom response types for simplifying these common tasks. +## Text Responses + +`Zend\Diactoros\Response\TextResponse` creates a plain text response. It sets the +`Content-Type` header to `text/plain` by default: + +```php +$response = new TextResponse('Hello world!'); +``` + +The constructor accepts two additional arguments: a status code and an array of headers. + +```php +$response = new TextResponse($text, 200, ['Content-Type' => ['text/csv']]); +``` + ## HTML Responses `Zend\Diactoros\Response\HtmlResponse` allows specifying HTML as a payload, and sets the diff --git a/src/Response/HtmlResponse.php b/src/Response/HtmlResponse.php index d298ee01..33426094 100644 --- a/src/Response/HtmlResponse.php +++ b/src/Response/HtmlResponse.php @@ -41,7 +41,7 @@ public function __construct($html, $status = 200, array $headers = []) parent::__construct( $this->createBody($html), $status, - $this->injectContentType('text/html', $headers) + $this->injectContentType('text/html; charset=utf-8', $headers) ); } diff --git a/src/Response/TextResponse.php b/src/Response/TextResponse.php new file mode 100644 index 00000000..bcf32d01 --- /dev/null +++ b/src/Response/TextResponse.php @@ -0,0 +1,73 @@ +createBody($text), + $status, + $this->injectContentType('text/plain; charset=utf-8', $headers) + ); + } + + /** + * Create the message body. + * + * @param string|StreamInterface $text + * @return StreamInterface + * @throws InvalidArgumentException if $html is neither a string or stream. + */ + private function createBody($text) + { + if ($text instanceof StreamInterface) { + return $text; + } + + if (! is_string($text)) { + throw new InvalidArgumentException(sprintf( + 'Invalid content (%s) provided to %s', + (is_object($text) ? get_class($text) : gettype($text)), + __CLASS__ + )); + } + + $body = new Stream('php://temp', 'wb+'); + $body->write($text); + return $body; + } +} diff --git a/test/Response/HtmlResponseTest.php b/test/Response/HtmlResponseTest.php index d2e43e15..e7489910 100644 --- a/test/Response/HtmlResponseTest.php +++ b/test/Response/HtmlResponseTest.php @@ -43,7 +43,7 @@ public function testConstructorAllowsPassingHeaders() $response = new HtmlResponse($body, $status, $headers); $this->assertEquals(['foo-bar'], $response->getHeader('x-custom')); - $this->assertEquals('text/html', $response->getHeaderLine('content-type')); + $this->assertEquals('text/html; charset=utf-8', $response->getHeaderLine('content-type')); $this->assertEquals(404, $response->getStatusCode()); $this->assertSame($body, (string) $response->getBody()); } diff --git a/test/Response/TextResponseTest.php b/test/Response/TextResponseTest.php new file mode 100644 index 00000000..56403cff --- /dev/null +++ b/test/Response/TextResponseTest.php @@ -0,0 +1,82 @@ +assertSame($body, (string) $response->getBody()); + $this->assertEquals(200, $response->getStatusCode()); + } + + public function testConstructorAllowsPassingStatus() + { + $body = 'Uh oh not found'; + $status = 404; + + $response = new TextResponse($body, $status); + $this->assertEquals(404, $response->getStatusCode()); + $this->assertSame($body, (string) $response->getBody()); + } + + public function testConstructorAllowsPassingHeaders() + { + $body = 'Uh oh not found'; + $status = 404; + $headers = [ + 'x-custom' => [ 'foo-bar' ], + ]; + + $response = new TextResponse($body, $status, $headers); + $this->assertEquals(['foo-bar'], $response->getHeader('x-custom')); + $this->assertEquals('text/plain; charset=utf-8', $response->getHeaderLine('content-type')); + $this->assertEquals(404, $response->getStatusCode()); + $this->assertSame($body, (string) $response->getBody()); + } + + public function testAllowsStreamsForResponseBody() + { + $stream = $this->prophesize('Psr\Http\Message\StreamInterface'); + $body = $stream->reveal(); + $response = new TextResponse($body); + $this->assertSame($body, $response->getBody()); + } + + public function invalidContent() + { + return [ + 'null' => [null], + 'true' => [true], + 'false' => [false], + 'zero' => [0], + 'int' => [1], + 'zero-float' => [0.0], + 'float' => [1.1], + 'array' => [['php://temp']], + 'object' => [(object) ['php://temp']], + ]; + } + + /** + * @dataProvider invalidContent + * @expectedException \InvalidArgumentException + */ + public function testRaisesExceptionforNonStringNonStreamBodyContent($body) + { + new TextResponse($body); + } +}