Refactor Transmitter
This commit is contained in:
parent
8649090774
commit
4796e1d5c5
|
|
@ -53,25 +53,26 @@ class Transmitter implements TransmitterInterface
|
||||||
$this->chunkSize = $chunkSize;
|
$this->chunkSize = $chunkSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function prepareResponse(
|
private function prepareResponse(
|
||||||
ServerRequestInterface $request,
|
ServerRequestInterface $request,
|
||||||
ResponseInterface $response
|
ResponseInterface $response
|
||||||
): ResponseInterface {
|
): ResponseInterface {
|
||||||
|
|
||||||
// Add a Content-length header to the response when all of these are true:
|
// Add 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 Content-length header
|
||||||
// - Response does not have a Transfer-encoding: chunked header
|
// - Response does not have a Transfer-encoding: chunked header
|
||||||
// - Response body stream is readable and reports a non-null size
|
// - Response body stream is readable and reports a non-null size
|
||||||
//
|
//
|
||||||
if (!$response->hasHeader('Content-length')
|
$contentLengthMissing = !$response->hasHeader('Content-length');
|
||||||
&& !(strtolower($response->getHeaderLine('Transfer-encoding')) === 'chunked')
|
$notChunked = strtolower($response->getHeaderLine('Transfer-encoding'))
|
||||||
) {
|
!== 'chunked';
|
||||||
$size = $response->getBody()->getSize();
|
$size = $response->getBody()->getSize();
|
||||||
if ($size !== null) {
|
|
||||||
$response = $response->withHeader('Content-length', (string) $size);
|
if ($contentLengthMissing && $notChunked && $size !== null) {
|
||||||
}
|
$response = $response->withHeader('Content-length', (string) $size);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace WellRESTed\Transmission;
|
|
||||||
|
|
||||||
class HeaderStack
|
|
||||||
{
|
|
||||||
private static $headers;
|
|
||||||
|
|
||||||
public static function reset()
|
|
||||||
{
|
|
||||||
self::$headers = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function push($header)
|
|
||||||
{
|
|
||||||
self::$headers[] = $header;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function getHeaders()
|
|
||||||
{
|
|
||||||
return self::$headers;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function header($string, $dummy = true)
|
|
||||||
{
|
|
||||||
HeaderStack::push($string);
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace WellRESTed\Test\Unit\Transmission;
|
namespace WellRESTed\Transmission;
|
||||||
|
|
||||||
use Prophecy\Argument;
|
use Prophecy\Argument;
|
||||||
use Prophecy\PhpUnit\ProphecyTrait;
|
use Prophecy\PhpUnit\ProphecyTrait;
|
||||||
|
|
@ -9,10 +9,6 @@ use RuntimeException;
|
||||||
use WellRESTed\Message\Response;
|
use WellRESTed\Message\Response;
|
||||||
use WellRESTed\Message\ServerRequest;
|
use WellRESTed\Message\ServerRequest;
|
||||||
use WellRESTed\Test\TestCase;
|
use WellRESTed\Test\TestCase;
|
||||||
use WellRESTed\Transmission\HeaderStack;
|
|
||||||
use WellRESTed\Transmission\Transmitter;
|
|
||||||
|
|
||||||
require_once __DIR__ . '/../../../src/HeaderStack.php';
|
|
||||||
|
|
||||||
class TransmitterTest extends TestCase
|
class TransmitterTest extends TestCase
|
||||||
{
|
{
|
||||||
|
|
@ -40,14 +36,14 @@ class TransmitterTest extends TestCase
|
||||||
->withBody($stream);
|
->withBody($stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSendStatusCodeWithReasonPhrase()
|
public function testSendStatusCodeWithReasonPhrase(): void
|
||||||
{
|
{
|
||||||
$transmitter = new Transmitter();
|
$transmitter = new Transmitter();
|
||||||
$transmitter->transmit($this->request, $this->response);
|
$transmitter->transmit($this->request, $this->response);
|
||||||
$this->assertContains('HTTP/1.1 200 OK', HeaderStack::getHeaders());
|
$this->assertContains('HTTP/1.1 200 OK', HeaderStack::getHeaders());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSendStatusCodeWithoutReasonPhrase()
|
public function testSendStatusCodeWithoutReasonPhrase(): void
|
||||||
{
|
{
|
||||||
$this->response = $this->response->withStatus(999);
|
$this->response = $this->response->withStatus(999);
|
||||||
|
|
||||||
|
|
@ -56,8 +52,11 @@ class TransmitterTest extends TestCase
|
||||||
$this->assertContains('HTTP/1.1 999', HeaderStack::getHeaders());
|
$this->assertContains('HTTP/1.1 999', HeaderStack::getHeaders());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @dataProvider headerProvider */
|
/**
|
||||||
public function testSendsHeaders($header)
|
* @dataProvider headerProvider
|
||||||
|
* @param string $header
|
||||||
|
*/
|
||||||
|
public function testSendsHeaders(string $header): void
|
||||||
{
|
{
|
||||||
$this->response = $this->response
|
$this->response = $this->response
|
||||||
->withHeader('Content-length', ['2048'])
|
->withHeader('Content-length', ['2048'])
|
||||||
|
|
@ -68,7 +67,7 @@ class TransmitterTest extends TestCase
|
||||||
$this->assertContains($header, HeaderStack::getHeaders());
|
$this->assertContains($header, HeaderStack::getHeaders());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function headerProvider()
|
public function headerProvider(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
['Content-length: 2048'],
|
['Content-length: 2048'],
|
||||||
|
|
@ -77,7 +76,7 @@ class TransmitterTest extends TestCase
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testOutputsBody()
|
public function testOutputsBody(): void
|
||||||
{
|
{
|
||||||
$content = 'Hello, world!';
|
$content = 'Hello, world!';
|
||||||
|
|
||||||
|
|
@ -95,7 +94,7 @@ class TransmitterTest extends TestCase
|
||||||
$this->assertEquals($content, $captured);
|
$this->assertEquals($content, $captured);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testOutputsBodyInChunks()
|
public function testOutputsBodyInChunks(): void
|
||||||
{
|
{
|
||||||
$content = 'Hello, world!';
|
$content = 'Hello, world!';
|
||||||
$chunkSize = 3;
|
$chunkSize = 3;
|
||||||
|
|
@ -128,7 +127,7 @@ class TransmitterTest extends TestCase
|
||||||
$this->assertEquals($content, $captured);
|
$this->assertEquals($content, $captured);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testOutputsUnseekableStreamInChunks()
|
public function testOutputsUnseekableStreamInChunks(): void
|
||||||
{
|
{
|
||||||
$content = 'Hello, world!';
|
$content = 'Hello, world!';
|
||||||
$chunkSize = 3;
|
$chunkSize = 3;
|
||||||
|
|
@ -164,7 +163,7 @@ class TransmitterTest extends TestCase
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// Preparation
|
// Preparation
|
||||||
|
|
||||||
public function testAddContentLengthHeader()
|
public function testAddContentLengthHeader(): void
|
||||||
{
|
{
|
||||||
$bodySize = 1024;
|
$bodySize = 1024;
|
||||||
$this->body->isReadable()->willReturn(true);
|
$this->body->isReadable()->willReturn(true);
|
||||||
|
|
@ -178,7 +177,7 @@ class TransmitterTest extends TestCase
|
||||||
$this->assertContains("Content-length: $bodySize", HeaderStack::getHeaders());
|
$this->assertContains("Content-length: $bodySize", HeaderStack::getHeaders());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testDoesNotReplaceContentLengthHeaderWhenContentLengthIsAlreadySet()
|
public function testDoesNotReplaceContentLengthHeaderWhenContentLengthIsAlreadySet(): void
|
||||||
{
|
{
|
||||||
$streamSize = 1024;
|
$streamSize = 1024;
|
||||||
$headerSize = 2048;
|
$headerSize = 2048;
|
||||||
|
|
@ -196,7 +195,7 @@ class TransmitterTest extends TestCase
|
||||||
$this->assertContains("Content-length: $headerSize", HeaderStack::getHeaders());
|
$this->assertContains("Content-length: $headerSize", HeaderStack::getHeaders());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testDoesNotAddContentLengthHeaderWhenTransferEncodingIsChunked()
|
public function testDoesNotAddContentLengthHeaderWhenTransferEncodingIsChunked(): void
|
||||||
{
|
{
|
||||||
$bodySize = 1024;
|
$bodySize = 1024;
|
||||||
|
|
||||||
|
|
@ -213,7 +212,7 @@ class TransmitterTest extends TestCase
|
||||||
$this->assertArrayDoesNotContainValueWithPrefix(HeaderStack::getHeaders(), 'Content-length:');
|
$this->assertArrayDoesNotContainValueWithPrefix(HeaderStack::getHeaders(), 'Content-length:');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testDoesNotAddContentLengthHeaderWhenBodySizeIsNull()
|
public function testDoesNotAddContentLengthHeaderWhenBodySizeIsNull(): void
|
||||||
{
|
{
|
||||||
$this->body->isReadable()->willReturn(true);
|
$this->body->isReadable()->willReturn(true);
|
||||||
$this->body->__toString()->willReturn('');
|
$this->body->__toString()->willReturn('');
|
||||||
|
|
@ -226,7 +225,7 @@ class TransmitterTest extends TestCase
|
||||||
$this->assertArrayDoesNotContainValueWithPrefix(HeaderStack::getHeaders(), 'Content-length:');
|
$this->assertArrayDoesNotContainValueWithPrefix(HeaderStack::getHeaders(), 'Content-length:');
|
||||||
}
|
}
|
||||||
|
|
||||||
private function assertArrayDoesNotContainValueWithPrefix($arr, $prefix)
|
private function assertArrayDoesNotContainValueWithPrefix(array $arr, string $prefix): void
|
||||||
{
|
{
|
||||||
$normalPrefix = strtolower($prefix);
|
$normalPrefix = strtolower($prefix);
|
||||||
foreach ($arr as $item) {
|
foreach ($arr as $item) {
|
||||||
|
|
@ -238,3 +237,33 @@ class TransmitterTest extends TestCase
|
||||||
$this->assertTrue(true);
|
$this->assertTrue(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Declare header function in this namespace so the class under test will use
|
||||||
|
// this instead of the internal global functions during testing.
|
||||||
|
|
||||||
|
class HeaderStack
|
||||||
|
{
|
||||||
|
private static $headers;
|
||||||
|
|
||||||
|
public static function reset()
|
||||||
|
{
|
||||||
|
self::$headers = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function push($header)
|
||||||
|
{
|
||||||
|
self::$headers[] = $header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getHeaders()
|
||||||
|
{
|
||||||
|
return self::$headers;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function header($string, $dummy = true)
|
||||||
|
{
|
||||||
|
HeaderStack::push($string);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue