From 788526eec3b44b80d830b822e3a5573d85465564 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Sat, 25 Jul 2020 13:15:01 +0200 Subject: [PATCH] Internal refactoring, remove unneeded MessageFactory helper class This is an internal preparation only and does not affect any public APIs. Some internal logic has been refactored and moved to classes with better cohesion. This is done in preparation for upcoming improvements to the `Transfer-Encoding: chunked` response header. --- src/Browser.php | 20 ++-- src/Client/Response.php | 15 ++- src/Io/MessageFactory.php | 78 ------------ src/Io/Sender.php | 29 +++-- src/Io/Transaction.php | 14 +-- tests/FunctionalBrowserTest.php | 62 ++++++++-- tests/Io/MessageFactoryTest.php | 135 --------------------- tests/Io/SenderTest.php | 36 +++--- tests/Io/TransactionTest.php | 204 +++++++++++++------------------- 9 files changed, 199 insertions(+), 394 deletions(-) delete mode 100644 src/Io/MessageFactory.php delete mode 100644 tests/Io/MessageFactoryTest.php diff --git a/src/Browser.php b/src/Browser.php index 48e64fcb..91604994 100644 --- a/src/Browser.php +++ b/src/Browser.php @@ -3,9 +3,10 @@ namespace React\Http; use Psr\Http\Message\ResponseInterface; +use RingCentral\Psr7\Request; use RingCentral\Psr7\Uri; use React\EventLoop\LoopInterface; -use React\Http\Io\MessageFactory; +use React\Http\Io\ReadableBodyStream; use React\Http\Io\Sender; use React\Http\Io\Transaction; use React\Promise\PromiseInterface; @@ -19,7 +20,6 @@ class Browser { private $transaction; - private $messageFactory; private $baseUrl; private $protocolVersion = '1.1'; @@ -59,10 +59,8 @@ class Browser */ public function __construct(LoopInterface $loop, ConnectorInterface $connector = null) { - $this->messageFactory = new MessageFactory(); $this->transaction = new Transaction( - Sender::createFromLoop($loop, $connector, $this->messageFactory), - $this->messageFactory, + Sender::createFromLoop($loop, $connector), $loop ); } @@ -721,18 +719,22 @@ private function withOptions(array $options) * @param string $method * @param string $url * @param array $headers - * @param string|ReadableStreamInterface $contents + * @param string|ReadableStreamInterface $body * @return PromiseInterface */ - private function requestMayBeStreaming($method, $url, array $headers = array(), $contents = '') + private function requestMayBeStreaming($method, $url, array $headers = array(), $body = '') { if ($this->baseUrl !== null) { // ensure we're actually below the base URL $url = Uri::resolve($this->baseUrl, $url); } - $request = $this->messageFactory->request($method, $url, $headers, $contents, $this->protocolVersion); + if ($body instanceof ReadableStreamInterface) { + $body = new ReadableBodyStream($body); + } - return $this->transaction->send($request); + return $this->transaction->send( + new Request($method, $url, $headers, $body, $this->protocolVersion) + ); } } diff --git a/src/Client/Response.php b/src/Client/Response.php index be19eb4c..2de64bb0 100644 --- a/src/Client/Response.php +++ b/src/Client/Response.php @@ -86,11 +86,24 @@ private function getHeader($name) return isset($normalized[$name]) ? (array)$normalized[$name] : array(); } - private function getHeaderLine($name) + /** + * @param string $name + * @return string + */ + public function getHeaderLine($name) { return implode(', ' , $this->getHeader($name)); } + /** + * @param string $name + * @return bool + */ + public function hasHeader($name) + { + return $this->getHeader($name) !== array(); + } + /** @internal */ public function handleData($data) { diff --git a/src/Io/MessageFactory.php b/src/Io/MessageFactory.php deleted file mode 100644 index f3d0993d..00000000 --- a/src/Io/MessageFactory.php +++ /dev/null @@ -1,78 +0,0 @@ -body($content), $protocolVersion); - } - - /** - * Creates a new instance of ResponseInterface for the given response parameters - * - * @param string $protocolVersion - * @param int $status - * @param string $reason - * @param array $headers - * @param ReadableStreamInterface|string $body - * @param ?string $requestMethod - * @return Response - * @uses self::body() - */ - public function response($protocolVersion, $status, $reason, $headers = array(), $body = '', $requestMethod = null) - { - $response = new Response($status, $headers, $body instanceof ReadableStreamInterface ? null : $body, $protocolVersion, $reason); - - if ($body instanceof ReadableStreamInterface) { - $length = null; - $code = $response->getStatusCode(); - if ($requestMethod === 'HEAD' || ($code >= 100 && $code < 200) || $code == 204 || $code == 304) { - $length = 0; - } elseif (\strtolower($response->getHeaderLine('Transfer-Encoding')) === 'chunked') { - $length = null; - } elseif ($response->hasHeader('Content-Length')) { - $length = (int)$response->getHeaderLine('Content-Length'); - } - - $response = $response->withBody(new ReadableBodyStream($body, $length)); - } - - return $response; - } - - /** - * Creates a new instance of StreamInterface for the given body contents - * - * @param ReadableStreamInterface|string $body - * @return StreamInterface - */ - public function body($body) - { - if ($body instanceof ReadableStreamInterface) { - return new ReadableBodyStream($body); - } - - return \RingCentral\Psr7\stream_for($body); - } -} diff --git a/src/Io/Sender.php b/src/Io/Sender.php index 6f3367e5..6cba0495 100644 --- a/src/Io/Sender.php +++ b/src/Io/Sender.php @@ -6,6 +6,7 @@ use React\EventLoop\LoopInterface; use React\Http\Client\Client as HttpClient; use React\Http\Client\Response as ResponseStream; +use React\Http\Message\Response; use React\Promise\PromiseInterface; use React\Promise\Deferred; use React\Socket\ConnectorInterface; @@ -47,13 +48,12 @@ class Sender * @param ConnectorInterface|null $connector * @return self */ - public static function createFromLoop(LoopInterface $loop, ConnectorInterface $connector = null, MessageFactory $messageFactory) + public static function createFromLoop(LoopInterface $loop, ConnectorInterface $connector = null) { - return new self(new HttpClient($loop, $connector), $messageFactory); + return new self(new HttpClient($loop, $connector)); } private $http; - private $messageFactory; /** * [internal] Instantiate Sender @@ -61,10 +61,9 @@ public static function createFromLoop(LoopInterface $loop, ConnectorInterface $c * @param HttpClient $http * @internal */ - public function __construct(HttpClient $http, MessageFactory $messageFactory) + public function __construct(HttpClient $http) { $this->http = $http; - $this->messageFactory = $messageFactory; } /** @@ -109,16 +108,22 @@ public function send(RequestInterface $request) $deferred->reject($error); }); - $messageFactory = $this->messageFactory; - $requestStream->on('response', function (ResponseStream $responseStream) use ($deferred, $messageFactory, $request) { + $requestStream->on('response', function (ResponseStream $responseStream) use ($deferred, $request) { + $length = null; + $code = $responseStream->getCode(); + if ($request->getMethod() === 'HEAD' || ($code >= 100 && $code < 200) || $code == 204 || $code == 304) { + $length = 0; + } elseif ($responseStream->hasHeader('Content-Length')) { + $length = (int) $responseStream->getHeaderLine('Content-Length'); + } + // apply response header values from response stream - $deferred->resolve($messageFactory->response( - $responseStream->getVersion(), + $deferred->resolve(new Response( $responseStream->getCode(), - $responseStream->getReasonPhrase(), $responseStream->getHeaders(), - $responseStream, - $request->getMethod() + new ReadableBodyStream($responseStream, $length), + $responseStream->getVersion(), + $responseStream->getReasonPhrase() )); }); diff --git a/src/Io/Transaction.php b/src/Io/Transaction.php index 93741dcc..9449503f 100644 --- a/src/Io/Transaction.php +++ b/src/Io/Transaction.php @@ -5,6 +5,7 @@ use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\UriInterface; +use RingCentral\Psr7\Request; use RingCentral\Psr7\Uri; use React\EventLoop\LoopInterface; use React\Http\Message\ResponseException; @@ -18,7 +19,6 @@ class Transaction { private $sender; - private $messageFactory; private $loop; // context: http.timeout (ini_get('default_socket_timeout'): 60) @@ -37,10 +37,9 @@ class Transaction private $maximumSize = 16777216; // 16 MiB = 2^24 bytes - public function __construct(Sender $sender, MessageFactory $messageFactory, LoopInterface $loop) + public function __construct(Sender $sender, LoopInterface $loop) { $this->sender = $sender; - $this->messageFactory = $messageFactory; $this->loop = $loop; } @@ -55,7 +54,7 @@ public function withOptions(array $options) if (property_exists($transaction, $name)) { // restore default value if null is given if ($value === null) { - $default = new self($this->sender, $this->messageFactory, $this->loop); + $default = new self($this->sender, $this->loop); $value = $default->$name; } @@ -186,11 +185,10 @@ public function bufferResponse(ResponseInterface $response, $deferred) } // buffer stream and resolve with buffered body - $messageFactory = $this->messageFactory; $maximumSize = $this->maximumSize; $promise = \React\Promise\Stream\buffer($stream, $maximumSize)->then( - function ($body) use ($response, $messageFactory) { - return $response->withBody($messageFactory->body($body)); + function ($body) use ($response) { + return $response->withBody(\RingCentral\Psr7\stream_for($body)); }, function ($e) use ($stream, $maximumSize) { // try to close stream if buffering fails (or is cancelled) @@ -280,7 +278,7 @@ private function makeRedirectRequest(RequestInterface $request, UriInterface $lo // naïve approach.. $method = ($request->getMethod() === 'HEAD') ? 'HEAD' : 'GET'; - return $this->messageFactory->request($method, $location, $request->getHeaders()); + return new Request($method, $location, $request->getHeaders()); } private function progress($name, array $args = array()) diff --git a/tests/FunctionalBrowserTest.php b/tests/FunctionalBrowserTest.php index f4495565..59cba0b9 100644 --- a/tests/FunctionalBrowserTest.php +++ b/tests/FunctionalBrowserTest.php @@ -64,14 +64,22 @@ public function setUpBrowserAndServer() ); } - if ($path === '/status/300') { + if ($path === '/status/204') { return new Response( - 300, + 204, array(), '' ); } + if ($path === '/status/304') { + return new Response( + 304, + array(), + 'Not modified' + ); + } + if ($path === '/status/404') { return new Response( 404, @@ -308,12 +316,24 @@ public function testFollowRedirectsZeroRejectsOnRedirect() Block\await($browser->get($this->base . 'redirect-to?url=get'), $this->loop); } - /** - * @doesNotPerformAssertions - */ - public function testResponseStatus300WithoutLocationShouldResolveWithoutFollowingRedirect() + public function testResponseStatus204ShouldResolveWithEmptyBody() { - Block\await($this->browser->get($this->base . 'status/300'), $this->loop); + $response = Block\await($this->browser->get($this->base . 'status/204'), $this->loop); + $this->assertFalse($response->hasHeader('Content-Length')); + + $body = $response->getBody(); + $this->assertEquals(0, $body->getSize()); + $this->assertEquals('', (string) $body); + } + + public function testResponseStatus304ShouldResolveWithEmptyBodyButContentLengthResponseHeader() + { + $response = Block\await($this->browser->get($this->base . 'status/304'), $this->loop); + $this->assertEquals('12', $response->getHeaderLine('Content-Length')); + + $body = $response->getBody(); + $this->assertEquals(0, $body->getSize()); + $this->assertEquals('', (string) $body); } /** @@ -595,9 +615,33 @@ public function testSendsExplicitHttp10Request() public function testHeadRequestReceivesResponseWithEmptyBodyButWithContentLengthResponseHeader() { $response = Block\await($this->browser->head($this->base . 'get'), $this->loop); - $this->assertEquals('', (string)$response->getBody()); - $this->assertEquals(0, $response->getBody()->getSize()); $this->assertEquals('5', $response->getHeaderLine('Content-Length')); + + $body = $response->getBody(); + $this->assertEquals(0, $body->getSize()); + $this->assertEquals('', (string) $body); + } + + public function testRequestStreamingGetReceivesResponseWithStreamingBodyAndKnownSize() + { + $response = Block\await($this->browser->requestStreaming('GET', $this->base . 'get'), $this->loop); + $this->assertEquals('5', $response->getHeaderLine('Content-Length')); + + $body = $response->getBody(); + $this->assertEquals(5, $body->getSize()); + $this->assertEquals('', (string) $body); + $this->assertInstanceOf('React\Stream\ReadableStreamInterface', $body); + } + + public function testRequestStreamingGetReceivesResponseWithStreamingBodyAndUnknownSizeFromStreamingEndpoint() + { + $response = Block\await($this->browser->requestStreaming('GET', $this->base . 'stream/1'), $this->loop); + $this->assertFalse($response->hasHeader('Content-Length')); + + $body = $response->getBody(); + $this->assertNull($body->getSize()); + $this->assertEquals('', (string) $body); + $this->assertInstanceOf('React\Stream\ReadableStreamInterface', $body); } public function testRequestStreamingGetReceivesStreamingResponseBody() diff --git a/tests/Io/MessageFactoryTest.php b/tests/Io/MessageFactoryTest.php deleted file mode 100644 index ae2dcdf9..00000000 --- a/tests/Io/MessageFactoryTest.php +++ /dev/null @@ -1,135 +0,0 @@ -messageFactory = new MessageFactory(); - } - - public function testBodyString() - { - $body = $this->messageFactory->body('hi'); - - $this->assertInstanceOf('Psr\Http\Message\StreamInterface', $body); - $this->assertNotInstanceOf('React\Stream\ReadableStreamInterface', $body); - $this->assertEquals(2, $body->getSize()); - $this->assertEquals('hi', (string)$body); - } - - public function testBodyReadableStream() - { - $stream = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock(); - $body = $this->messageFactory->body($stream); - - $this->assertInstanceOf('Psr\Http\Message\StreamInterface', $body); - $this->assertInstanceOf('React\Stream\ReadableStreamInterface', $body); - $this->assertEquals(null, $body->getSize()); - $this->assertEquals('', (string)$body); - } - - public function testResponseWithBodyString() - { - $response = $this->messageFactory->response('1.1', 200, 'OK', array(), 'hi'); - - $body = $response->getBody(); - $this->assertInstanceOf('Psr\Http\Message\StreamInterface', $body); - $this->assertNotInstanceOf('React\Stream\ReadableStreamInterface', $body); - $this->assertEquals(2, $body->getSize()); - $this->assertEquals('hi', (string)$body); - } - - public function testResponseWithStreamingBodyHasUnknownSizeByDefault() - { - $stream = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock(); - $response = $this->messageFactory->response('1.1', 200, 'OK', array(), $stream); - - $body = $response->getBody(); - $this->assertInstanceOf('Psr\Http\Message\StreamInterface', $body); - $this->assertInstanceOf('React\Stream\ReadableStreamInterface', $body); - $this->assertNull($body->getSize()); - $this->assertEquals('', (string)$body); - } - - public function testResponseWithStreamingBodyHasSizeFromContentLengthHeader() - { - $stream = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock(); - $response = $this->messageFactory->response('1.1', 200, 'OK', array('Content-Length' => '100'), $stream); - - $body = $response->getBody(); - $this->assertInstanceOf('Psr\Http\Message\StreamInterface', $body); - $this->assertInstanceOf('React\Stream\ReadableStreamInterface', $body); - $this->assertEquals(100, $body->getSize()); - $this->assertEquals('', (string)$body); - } - - public function testResponseWithStreamingBodyHasUnknownSizeWithTransferEncodingChunkedHeader() - { - $stream = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock(); - $response = $this->messageFactory->response('1.1', 200, 'OK', array('Transfer-Encoding' => 'chunked'), $stream); - - $body = $response->getBody(); - $this->assertInstanceOf('Psr\Http\Message\StreamInterface', $body); - $this->assertInstanceOf('React\Stream\ReadableStreamInterface', $body); - $this->assertNull($body->getSize()); - $this->assertEquals('', (string)$body); - } - - public function testResponseWithStreamingBodyHasZeroSizeForInformationalResponse() - { - $stream = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock(); - $response = $this->messageFactory->response('1.1', 101, 'OK', array('Content-Length' => '100'), $stream); - - $body = $response->getBody(); - $this->assertInstanceOf('Psr\Http\Message\StreamInterface', $body); - $this->assertInstanceOf('React\Stream\ReadableStreamInterface', $body); - $this->assertEquals(0, $body->getSize()); - $this->assertEquals('', (string)$body); - } - - public function testResponseWithStreamingBodyHasZeroSizeForNoContentResponse() - { - $stream = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock(); - $response = $this->messageFactory->response('1.1', 204, 'OK', array('Content-Length' => '100'), $stream); - - $body = $response->getBody(); - $this->assertInstanceOf('Psr\Http\Message\StreamInterface', $body); - $this->assertInstanceOf('React\Stream\ReadableStreamInterface', $body); - $this->assertEquals(0, $body->getSize()); - $this->assertEquals('', (string)$body); - } - - public function testResponseWithStreamingBodyHasZeroSizeForNotModifiedResponse() - { - $stream = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock(); - $response = $this->messageFactory->response('1.1', 304, 'OK', array('Content-Length' => '100'), $stream); - - $body = $response->getBody(); - $this->assertInstanceOf('Psr\Http\Message\StreamInterface', $body); - $this->assertInstanceOf('React\Stream\ReadableStreamInterface', $body); - $this->assertEquals(0, $body->getSize()); - $this->assertEquals('', (string)$body); - } - - public function testResponseWithStreamingBodyHasZeroSizeForHeadRequestMethod() - { - $stream = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock(); - $response = $this->messageFactory->response('1.1', 200, 'OK', array('Content-Length' => '100'), $stream, 'HEAD'); - - $body = $response->getBody(); - $this->assertInstanceOf('Psr\Http\Message\StreamInterface', $body); - $this->assertInstanceOf('React\Stream\ReadableStreamInterface', $body); - $this->assertEquals(0, $body->getSize()); - $this->assertEquals('', (string)$body); - } -} diff --git a/tests/Io/SenderTest.php b/tests/Io/SenderTest.php index 35eb22e7..1c6d1d6b 100644 --- a/tests/Io/SenderTest.php +++ b/tests/Io/SenderTest.php @@ -26,7 +26,7 @@ public function setUpLoop() public function testCreateFromLoop() { - $sender = Sender::createFromLoop($this->loop, null, $this->getMockBuilder('React\Http\Io\MessageFactory')->getMock()); + $sender = Sender::createFromLoop($this->loop, null); $this->assertInstanceOf('React\Http\Io\Sender', $sender); } @@ -36,7 +36,7 @@ public function testSenderRejectsInvalidUri() $connector = $this->getMockBuilder('React\Socket\ConnectorInterface')->getMock(); $connector->expects($this->never())->method('connect'); - $sender = new Sender(new HttpClient($this->loop, $connector), $this->getMockBuilder('React\Http\Io\MessageFactory')->getMock()); + $sender = new Sender(new HttpClient($this->loop, $connector)); $request = new Request('GET', 'www.google.com'); @@ -51,7 +51,7 @@ public function testSenderConnectorRejection() $connector = $this->getMockBuilder('React\Socket\ConnectorInterface')->getMock(); $connector->expects($this->once())->method('connect')->willReturn(Promise\reject(new \RuntimeException('Rejected'))); - $sender = new Sender(new HttpClient($this->loop, $connector), $this->getMockBuilder('React\Http\Io\MessageFactory')->getMock()); + $sender = new Sender(new HttpClient($this->loop, $connector)); $request = new Request('GET', 'http://www.google.com/'); @@ -71,7 +71,7 @@ public function testSendPostWillAutomaticallySendContentLengthHeader() '1.1' )->willReturn($this->getMockBuilder('React\Http\Client\Request')->disableOriginalConstructor()->getMock()); - $sender = new Sender($client, $this->getMockBuilder('React\Http\Io\MessageFactory')->getMock()); + $sender = new Sender($client); $request = new Request('POST', 'http://www.google.com/', array(), 'hello'); $sender->send($request); @@ -87,7 +87,7 @@ public function testSendPostWillAutomaticallySendContentLengthZeroHeaderForEmpty '1.1' )->willReturn($this->getMockBuilder('React\Http\Client\Request')->disableOriginalConstructor()->getMock()); - $sender = new Sender($client, $this->getMockBuilder('React\Http\Io\MessageFactory')->getMock()); + $sender = new Sender($client); $request = new Request('POST', 'http://www.google.com/', array(), ''); $sender->send($request); @@ -106,7 +106,7 @@ public function testSendPostStreamWillAutomaticallySendTransferEncodingChunked() '1.1' )->willReturn($outgoing); - $sender = new Sender($client, $this->getMockBuilder('React\Http\Io\MessageFactory')->getMock()); + $sender = new Sender($client); $stream = new ThroughStream(); $request = new Request('POST', 'http://www.google.com/', array(), new ReadableBodyStream($stream)); @@ -122,7 +122,7 @@ public function testSendPostStreamWillAutomaticallyPipeChunkEncodeBodyForWriteAn $client = $this->getMockBuilder('React\Http\Client\Client')->disableOriginalConstructor()->getMock(); $client->expects($this->once())->method('request')->willReturn($outgoing); - $sender = new Sender($client, $this->getMockBuilder('React\Http\Io\MessageFactory')->getMock()); + $sender = new Sender($client); $stream = new ThroughStream(); $request = new Request('POST', 'http://www.google.com/', array(), new ReadableBodyStream($stream)); @@ -142,7 +142,7 @@ public function testSendPostStreamWillAutomaticallyPipeChunkEncodeBodyForEnd() $client = $this->getMockBuilder('React\Http\Client\Client')->disableOriginalConstructor()->getMock(); $client->expects($this->once())->method('request')->willReturn($outgoing); - $sender = new Sender($client, $this->getMockBuilder('React\Http\Io\MessageFactory')->getMock()); + $sender = new Sender($client); $stream = new ThroughStream(); $request = new Request('POST', 'http://www.google.com/', array(), new ReadableBodyStream($stream)); @@ -162,7 +162,7 @@ public function testSendPostStreamWillRejectWhenRequestBodyEmitsErrorEvent() $client = $this->getMockBuilder('React\Http\Client\Client')->disableOriginalConstructor()->getMock(); $client->expects($this->once())->method('request')->willReturn($outgoing); - $sender = new Sender($client, $this->getMockBuilder('React\Http\Io\MessageFactory')->getMock()); + $sender = new Sender($client); $expected = new \RuntimeException(); $stream = new ThroughStream(); @@ -192,7 +192,7 @@ public function testSendPostStreamWillRejectWhenRequestBodyClosesWithoutEnd() $client = $this->getMockBuilder('React\Http\Client\Client')->disableOriginalConstructor()->getMock(); $client->expects($this->once())->method('request')->willReturn($outgoing); - $sender = new Sender($client, $this->getMockBuilder('React\Http\Io\MessageFactory')->getMock()); + $sender = new Sender($client); $stream = new ThroughStream(); $request = new Request('POST', 'http://www.google.com/', array(), new ReadableBodyStream($stream)); @@ -220,7 +220,7 @@ public function testSendPostStreamWillNotRejectWhenRequestBodyClosesAfterEnd() $client = $this->getMockBuilder('React\Http\Client\Client')->disableOriginalConstructor()->getMock(); $client->expects($this->once())->method('request')->willReturn($outgoing); - $sender = new Sender($client, $this->getMockBuilder('React\Http\Io\MessageFactory')->getMock()); + $sender = new Sender($client); $stream = new ThroughStream(); $request = new Request('POST', 'http://www.google.com/', array(), new ReadableBodyStream($stream)); @@ -247,7 +247,7 @@ public function testSendPostStreamWithExplicitContentLengthWillSendHeaderAsIs() '1.1' )->willReturn($this->getMockBuilder('React\Http\Client\Request')->disableOriginalConstructor()->getMock()); - $sender = new Sender($client, $this->getMockBuilder('React\Http\Io\MessageFactory')->getMock()); + $sender = new Sender($client); $stream = new ThroughStream(); $request = new Request('POST', 'http://www.google.com/', array('Content-Length' => '100'), new ReadableBodyStream($stream)); @@ -264,7 +264,7 @@ public function testSendGetWillNotPassContentLengthHeaderForEmptyRequestBody() '1.1' )->willReturn($this->getMockBuilder('React\Http\Client\Request')->disableOriginalConstructor()->getMock()); - $sender = new Sender($client, $this->getMockBuilder('React\Http\Io\MessageFactory')->getMock()); + $sender = new Sender($client); $request = new Request('GET', 'http://www.google.com/'); $sender->send($request); @@ -280,7 +280,7 @@ public function testSendCustomMethodWillNotPassContentLengthHeaderForEmptyReques '1.1' )->willReturn($this->getMockBuilder('React\Http\Client\Request')->disableOriginalConstructor()->getMock()); - $sender = new Sender($client, $this->getMockBuilder('React\Http\Io\MessageFactory')->getMock()); + $sender = new Sender($client); $request = new Request('CUSTOM', 'http://www.google.com/'); $sender->send($request); @@ -296,7 +296,7 @@ public function testSendCustomMethodWithExplicitContentLengthZeroWillBePassedAsI '1.1' )->willReturn($this->getMockBuilder('React\Http\Client\Request')->disableOriginalConstructor()->getMock()); - $sender = new Sender($client, $this->getMockBuilder('React\Http\Io\MessageFactory')->getMock()); + $sender = new Sender($client); $request = new Request('CUSTOM', 'http://www.google.com/', array('Content-Length' => '0')); $sender->send($request); @@ -311,7 +311,7 @@ public function testCancelRequestWillCancelConnector() $connector = $this->getMockBuilder('React\Socket\ConnectorInterface')->getMock(); $connector->expects($this->once())->method('connect')->willReturn($promise); - $sender = new Sender(new HttpClient($this->loop, $connector), $this->getMockBuilder('React\Http\Io\MessageFactory')->getMock()); + $sender = new Sender(new HttpClient($this->loop, $connector)); $request = new Request('GET', 'http://www.google.com/'); @@ -330,7 +330,7 @@ public function testCancelRequestWillCloseConnection() $connector = $this->getMockBuilder('React\Socket\ConnectorInterface')->getMock(); $connector->expects($this->once())->method('connect')->willReturn(Promise\resolve($connection)); - $sender = new Sender(new HttpClient($this->loop, $connector), $this->getMockBuilder('React\Http\Io\MessageFactory')->getMock()); + $sender = new Sender(new HttpClient($this->loop, $connector)); $request = new Request('GET', 'http://www.google.com/'); @@ -387,7 +387,7 @@ public function testRequestProtocolVersion(Request $Request, $method, $uri, $hea $http->expects($this->once())->method('request')->with($method, $uri, $headers, $protocolVersion)->willReturn($request); - $sender = new Sender($http, $this->getMockBuilder('React\Http\Io\MessageFactory')->getMock()); + $sender = new Sender($http); $sender->send($Request); } } diff --git a/tests/Io/TransactionTest.php b/tests/Io/TransactionTest.php index 88320bf0..384a74a6 100644 --- a/tests/Io/TransactionTest.php +++ b/tests/Io/TransactionTest.php @@ -5,7 +5,7 @@ use Clue\React\Block; use PHPUnit\Framework\MockObject\MockObject; use Psr\Http\Message\RequestInterface; -use React\Http\Io\MessageFactory; +use RingCentral\Psr7\Response; use React\Http\Io\Transaction; use React\Http\Message\ResponseException; use React\EventLoop\Factory; @@ -13,7 +13,8 @@ use React\Promise\Deferred; use React\Stream\ThroughStream; use React\Tests\Http\TestCase; -use RingCentral\Psr7\Response; +use RingCentral\Psr7\Request; +use React\Http\Io\ReadableBodyStream; class TransactionTest extends TestCase { @@ -21,7 +22,7 @@ public function testWithOptionsReturnsNewInstanceWithChangedOption() { $sender = $this->makeSenderMock(); $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); - $transaction = new Transaction($sender, new MessageFactory(), $loop); + $transaction = new Transaction($sender, $loop); $new = $transaction->withOptions(array('followRedirects' => false)); @@ -38,7 +39,7 @@ public function testWithOptionsDoesNotChangeOriginalInstance() { $sender = $this->makeSenderMock(); $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); - $transaction = new Transaction($sender, new MessageFactory(), $loop); + $transaction = new Transaction($sender, $loop); $transaction->withOptions(array('followRedirects' => false)); @@ -52,7 +53,7 @@ public function testWithOptionsNullValueReturnsNewInstanceWithDefaultOption() { $sender = $this->makeSenderMock(); $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); - $transaction = new Transaction($sender, new MessageFactory(), $loop); + $transaction = new Transaction($sender, $loop); $transaction = $transaction->withOptions(array('followRedirects' => false)); $transaction = $transaction->withOptions(array('followRedirects' => null)); @@ -65,8 +66,6 @@ public function testWithOptionsNullValueReturnsNewInstanceWithDefaultOption() public function testTimeoutExplicitOptionWillStartTimeoutTimer() { - $messageFactory = new MessageFactory(); - $timer = $this->getMockBuilder('React\EventLoop\TimerInterface')->getMock(); $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); $loop->expects($this->once())->method('addTimer')->with(2, $this->anything())->willReturn($timer); @@ -77,7 +76,7 @@ public function testTimeoutExplicitOptionWillStartTimeoutTimer() $sender = $this->getMockBuilder('React\Http\Io\Sender')->disableOriginalConstructor()->getMock(); $sender->expects($this->once())->method('send')->with($this->equalTo($request))->willReturn(new \React\Promise\Promise(function () { })); - $transaction = new Transaction($sender, $messageFactory, $loop); + $transaction = new Transaction($sender, $loop); $transaction = $transaction->withOptions(array('timeout' => 2)); $promise = $transaction->send($request); @@ -86,8 +85,6 @@ public function testTimeoutExplicitOptionWillStartTimeoutTimer() public function testTimeoutImplicitFromIniWillStartTimeoutTimer() { - $messageFactory = new MessageFactory(); - $timer = $this->getMockBuilder('React\EventLoop\TimerInterface')->getMock(); $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); $loop->expects($this->once())->method('addTimer')->with(2, $this->anything())->willReturn($timer); @@ -98,7 +95,7 @@ public function testTimeoutImplicitFromIniWillStartTimeoutTimer() $sender = $this->getMockBuilder('React\Http\Io\Sender')->disableOriginalConstructor()->getMock(); $sender->expects($this->once())->method('send')->with($this->equalTo($request))->willReturn(new \React\Promise\Promise(function () { })); - $transaction = new Transaction($sender, $messageFactory, $loop); + $transaction = new Transaction($sender, $loop); $old = ini_get('default_socket_timeout'); ini_set('default_socket_timeout', '2'); @@ -110,8 +107,6 @@ public function testTimeoutImplicitFromIniWillStartTimeoutTimer() public function testTimeoutExplicitOptionWillRejectWhenTimerFires() { - $messageFactory = new MessageFactory(); - $timeout = null; $timer = $this->getMockBuilder('React\EventLoop\TimerInterface')->getMock(); $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); @@ -126,7 +121,7 @@ public function testTimeoutExplicitOptionWillRejectWhenTimerFires() $sender = $this->getMockBuilder('React\Http\Io\Sender')->disableOriginalConstructor()->getMock(); $sender->expects($this->once())->method('send')->with($this->equalTo($request))->willReturn(new \React\Promise\Promise(function () { })); - $transaction = new Transaction($sender, $messageFactory, $loop); + $transaction = new Transaction($sender, $loop); $transaction = $transaction->withOptions(array('timeout' => 2)); $promise = $transaction->send($request); @@ -144,18 +139,16 @@ public function testTimeoutExplicitOptionWillRejectWhenTimerFires() public function testTimeoutExplicitOptionWillNotStartTimeoutWhenSenderResolvesImmediately() { - $messageFactory = new MessageFactory(); - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); $loop->expects($this->never())->method('addTimer'); $request = $this->getMockBuilder('Psr\Http\Message\RequestInterface')->getMock(); - $response = $messageFactory->response(1.0, 200, 'OK', array(), ''); + $response = new Response(200, array(), ''); $sender = $this->getMockBuilder('React\Http\Io\Sender')->disableOriginalConstructor()->getMock(); $sender->expects($this->once())->method('send')->with($this->equalTo($request))->willReturn(Promise\resolve($response)); - $transaction = new Transaction($sender, $messageFactory, $loop); + $transaction = new Transaction($sender, $loop); $transaction = $transaction->withOptions(array('timeout' => 0.001)); $promise = $transaction->send($request); @@ -165,21 +158,19 @@ public function testTimeoutExplicitOptionWillNotStartTimeoutWhenSenderResolvesIm public function testTimeoutExplicitOptionWillCancelTimeoutTimerWhenSenderResolvesLaterOn() { - $messageFactory = new MessageFactory(); - $timer = $this->getMockBuilder('React\EventLoop\TimerInterface')->getMock(); $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); $loop->expects($this->once())->method('addTimer')->willReturn($timer); $loop->expects($this->once())->method('cancelTimer')->with($timer); $request = $this->getMockBuilder('Psr\Http\Message\RequestInterface')->getMock(); - $response = $messageFactory->response(1.0, 200, 'OK', array(), ''); + $response = new Response(200, array(), ''); $deferred = new Deferred(); $sender = $this->getMockBuilder('React\Http\Io\Sender')->disableOriginalConstructor()->getMock(); $sender->expects($this->once())->method('send')->with($this->equalTo($request))->willReturn($deferred->promise()); - $transaction = new Transaction($sender, $messageFactory, $loop); + $transaction = new Transaction($sender, $loop); $transaction = $transaction->withOptions(array('timeout' => 0.001)); $promise = $transaction->send($request); @@ -191,8 +182,6 @@ public function testTimeoutExplicitOptionWillCancelTimeoutTimerWhenSenderResolve public function testTimeoutExplicitOptionWillNotStartTimeoutWhenSenderRejectsImmediately() { - $messageFactory = new MessageFactory(); - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); $loop->expects($this->never())->method('addTimer'); @@ -202,7 +191,7 @@ public function testTimeoutExplicitOptionWillNotStartTimeoutWhenSenderRejectsImm $sender = $this->getMockBuilder('React\Http\Io\Sender')->disableOriginalConstructor()->getMock(); $sender->expects($this->once())->method('send')->with($this->equalTo($request))->willReturn(Promise\reject($exception)); - $transaction = new Transaction($sender, $messageFactory, $loop); + $transaction = new Transaction($sender, $loop); $transaction = $transaction->withOptions(array('timeout' => 0.001)); $promise = $transaction->send($request); @@ -212,8 +201,6 @@ public function testTimeoutExplicitOptionWillNotStartTimeoutWhenSenderRejectsImm public function testTimeoutExplicitOptionWillCancelTimeoutTimerWhenSenderRejectsLaterOn() { - $messageFactory = new MessageFactory(); - $timer = $this->getMockBuilder('React\EventLoop\TimerInterface')->getMock(); $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); $loop->expects($this->once())->method('addTimer')->willReturn($timer); @@ -225,7 +212,7 @@ public function testTimeoutExplicitOptionWillCancelTimeoutTimerWhenSenderRejects $sender = $this->getMockBuilder('React\Http\Io\Sender')->disableOriginalConstructor()->getMock(); $sender->expects($this->once())->method('send')->with($this->equalTo($request))->willReturn($deferred->promise()); - $transaction = new Transaction($sender, $messageFactory, $loop); + $transaction = new Transaction($sender, $loop); $transaction = $transaction->withOptions(array('timeout' => 0.001)); $promise = $transaction->send($request); @@ -238,8 +225,6 @@ public function testTimeoutExplicitOptionWillCancelTimeoutTimerWhenSenderRejects public function testTimeoutExplicitNegativeWillNotStartTimeoutTimer() { - $messageFactory = new MessageFactory(); - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); $loop->expects($this->never())->method('addTimer'); @@ -248,7 +233,7 @@ public function testTimeoutExplicitNegativeWillNotStartTimeoutTimer() $sender = $this->getMockBuilder('React\Http\Io\Sender')->disableOriginalConstructor()->getMock(); $sender->expects($this->once())->method('send')->with($this->equalTo($request))->willReturn(new \React\Promise\Promise(function () { })); - $transaction = new Transaction($sender, $messageFactory, $loop); + $transaction = new Transaction($sender, $loop); $transaction = $transaction->withOptions(array('timeout' => -1)); $promise = $transaction->send($request); @@ -257,18 +242,16 @@ public function testTimeoutExplicitNegativeWillNotStartTimeoutTimer() public function testTimeoutExplicitOptionWillNotStartTimeoutTimerWhenRequestBodyIsStreaming() { - $messageFactory = new MessageFactory(); - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); $loop->expects($this->never())->method('addTimer'); $stream = new ThroughStream(); - $request = $messageFactory->request('POST', 'http://example.com', array(), $stream); + $request = new Request('POST', 'http://example.com', array(), new ReadableBodyStream($stream)); $sender = $this->getMockBuilder('React\Http\Io\Sender')->disableOriginalConstructor()->getMock(); $sender->expects($this->once())->method('send')->with($this->equalTo($request))->willReturn(new \React\Promise\Promise(function () { })); - $transaction = new Transaction($sender, $messageFactory, $loop); + $transaction = new Transaction($sender, $loop); $transaction = $transaction->withOptions(array('timeout' => 2)); $promise = $transaction->send($request); @@ -277,8 +260,6 @@ public function testTimeoutExplicitOptionWillNotStartTimeoutTimerWhenRequestBody public function testTimeoutExplicitOptionWillStartTimeoutTimerWhenStreamingRequestBodyIsAlreadyClosed() { - $messageFactory = new MessageFactory(); - $timer = $this->getMockBuilder('React\EventLoop\TimerInterface')->getMock(); $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); $loop->expects($this->once())->method('addTimer')->with(2, $this->anything())->willReturn($timer); @@ -286,12 +267,12 @@ public function testTimeoutExplicitOptionWillStartTimeoutTimerWhenStreamingReque $stream = new ThroughStream(); $stream->close(); - $request = $messageFactory->request('POST', 'http://example.com', array(), $stream); + $request = new Request('POST', 'http://example.com', array(), new ReadableBodyStream($stream)); $sender = $this->getMockBuilder('React\Http\Io\Sender')->disableOriginalConstructor()->getMock(); $sender->expects($this->once())->method('send')->with($this->equalTo($request))->willReturn(new \React\Promise\Promise(function () { })); - $transaction = new Transaction($sender, $messageFactory, $loop); + $transaction = new Transaction($sender, $loop); $transaction = $transaction->withOptions(array('timeout' => 2)); $promise = $transaction->send($request); @@ -300,20 +281,18 @@ public function testTimeoutExplicitOptionWillStartTimeoutTimerWhenStreamingReque public function testTimeoutExplicitOptionWillStartTimeoutTimerWhenStreamingRequestBodyClosesWhileSenderIsStillPending() { - $messageFactory = new MessageFactory(); - $timer = $this->getMockBuilder('React\EventLoop\TimerInterface')->getMock(); $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); $loop->expects($this->once())->method('addTimer')->with(2, $this->anything())->willReturn($timer); $loop->expects($this->never())->method('cancelTimer'); $stream = new ThroughStream(); - $request = $messageFactory->request('POST', 'http://example.com', array(), $stream); + $request = new Request('POST', 'http://example.com', array(), new ReadableBodyStream($stream)); $sender = $this->getMockBuilder('React\Http\Io\Sender')->disableOriginalConstructor()->getMock(); $sender->expects($this->once())->method('send')->with($this->equalTo($request))->willReturn(new \React\Promise\Promise(function () { })); - $transaction = new Transaction($sender, $messageFactory, $loop); + $transaction = new Transaction($sender, $loop); $transaction = $transaction->withOptions(array('timeout' => 2)); $promise = $transaction->send($request); @@ -324,19 +303,17 @@ public function testTimeoutExplicitOptionWillStartTimeoutTimerWhenStreamingReque public function testTimeoutExplicitOptionWillNotStartTimeoutTimerWhenStreamingRequestBodyClosesAfterSenderRejects() { - $messageFactory = new MessageFactory(); - $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); $loop->expects($this->never())->method('addTimer'); $stream = new ThroughStream(); - $request = $messageFactory->request('POST', 'http://example.com', array(), $stream); + $request = new Request('POST', 'http://example.com', array(), new ReadableBodyStream($stream)); $deferred = new Deferred(); $sender = $this->getMockBuilder('React\Http\Io\Sender')->disableOriginalConstructor()->getMock(); $sender->expects($this->once())->method('send')->with($this->equalTo($request))->willReturn($deferred->promise()); - $transaction = new Transaction($sender, $messageFactory, $loop); + $transaction = new Transaction($sender, $loop); $transaction = $transaction->withOptions(array('timeout' => 2)); $promise = $transaction->send($request); @@ -348,8 +325,6 @@ public function testTimeoutExplicitOptionWillNotStartTimeoutTimerWhenStreamingRe public function testTimeoutExplicitOptionWillRejectWhenTimerFiresAfterStreamingRequestBodyCloses() { - $messageFactory = new MessageFactory(); - $timeout = null; $timer = $this->getMockBuilder('React\EventLoop\TimerInterface')->getMock(); $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); @@ -360,12 +335,12 @@ public function testTimeoutExplicitOptionWillRejectWhenTimerFiresAfterStreamingR $loop->expects($this->never())->method('cancelTimer'); $stream = new ThroughStream(); - $request = $messageFactory->request('POST', 'http://example.com', array(), $stream); + $request = new Request('POST', 'http://example.com', array(), new ReadableBodyStream($stream)); $sender = $this->getMockBuilder('React\Http\Io\Sender')->disableOriginalConstructor()->getMock(); $sender->expects($this->once())->method('send')->with($this->equalTo($request))->willReturn(new \React\Promise\Promise(function () { })); - $transaction = new Transaction($sender, $messageFactory, $loop); + $transaction = new Transaction($sender, $loop); $transaction = $transaction->withOptions(array('timeout' => 2)); $promise = $transaction->send($request); @@ -393,7 +368,7 @@ public function testReceivingErrorResponseWillRejectWithResponseException() $sender = $this->makeSenderMock(); $sender->expects($this->once())->method('send')->with($this->equalTo($request))->willReturn(Promise\resolve($response)); - $transaction = new Transaction($sender, new MessageFactory(), $loop); + $transaction = new Transaction($sender, $loop); $transaction = $transaction->withOptions(array('timeout' => -1)); $promise = $transaction->send($request); @@ -408,7 +383,6 @@ public function testReceivingErrorResponseWillRejectWithResponseException() public function testReceivingStreamingBodyWillResolveWithBufferedResponseByDefault() { - $messageFactory = new MessageFactory(); $loop = Factory::create(); $stream = new ThroughStream(); @@ -418,13 +392,13 @@ public function testReceivingStreamingBodyWillResolveWithBufferedResponseByDefau }); $request = $this->getMockBuilder('Psr\Http\Message\RequestInterface')->getMock(); - $response = $messageFactory->response(1.0, 200, 'OK', array(), $stream); + $response = new Response(200, array(), new ReadableBodyStream($stream)); // mock sender to resolve promise with the given $response in response to the given $request $sender = $this->makeSenderMock(); $sender->expects($this->once())->method('send')->with($this->equalTo($request))->willReturn(Promise\resolve($response)); - $transaction = new Transaction($sender, $messageFactory, $loop); + $transaction = new Transaction($sender, $loop); $promise = $transaction->send($request); $response = Block\await($promise, $loop); @@ -435,7 +409,6 @@ public function testReceivingStreamingBodyWillResolveWithBufferedResponseByDefau public function testReceivingStreamingBodyWithSizeExceedingMaximumResponseBufferWillRejectAndCloseResponseStream() { - $messageFactory = new MessageFactory(); $loop = Factory::create(); $stream = new ThroughStream(); @@ -443,13 +416,13 @@ public function testReceivingStreamingBodyWithSizeExceedingMaximumResponseBuffer $request = $this->getMockBuilder('Psr\Http\Message\RequestInterface')->getMock(); - $response = $messageFactory->response(1.0, 200, 'OK', array('Content-Length' => '100000000'), $stream); + $response = new Response(200, array('Content-Length' => '100000000'), new ReadableBodyStream($stream, 100000000)); // mock sender to resolve promise with the given $response in response to the given $request $sender = $this->makeSenderMock(); $sender->expects($this->once())->method('send')->with($this->equalTo($request))->willReturn(Promise\resolve($response)); - $transaction = new Transaction($sender, $messageFactory, $loop); + $transaction = new Transaction($sender, $loop); $promise = $transaction->send($request); $this->setExpectedException('OverflowException'); @@ -458,7 +431,6 @@ public function testReceivingStreamingBodyWithSizeExceedingMaximumResponseBuffer public function testCancelBufferingResponseWillCloseStreamAndReject() { - $messageFactory = new MessageFactory(); $loop = Factory::create(); $stream = $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock(); @@ -466,13 +438,13 @@ public function testCancelBufferingResponseWillCloseStreamAndReject() $stream->expects($this->once())->method('close'); $request = $this->getMockBuilder('Psr\Http\Message\RequestInterface')->getMock(); - $response = $messageFactory->response(1.0, 200, 'OK', array(), $stream); + $response = new Response(200, array(), new ReadableBodyStream($stream)); // mock sender to resolve promise with the given $response in response to the given $request $sender = $this->makeSenderMock(); $sender->expects($this->once())->method('send')->with($this->equalTo($request))->willReturn(Promise\resolve($response)); - $transaction = new Transaction($sender, $messageFactory, $loop); + $transaction = new Transaction($sender, $loop); $promise = $transaction->send($request); $promise->cancel(); @@ -482,17 +454,16 @@ public function testCancelBufferingResponseWillCloseStreamAndReject() public function testReceivingStreamingBodyWillResolveWithStreamingResponseIfStreamingIsEnabled() { - $messageFactory = new MessageFactory(); $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); $request = $this->getMockBuilder('Psr\Http\Message\RequestInterface')->getMock(); - $response = $messageFactory->response(1.0, 200, 'OK', array(), $this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock()); + $response = new Response(200, array(), new ReadableBodyStream($this->getMockBuilder('React\Stream\ReadableStreamInterface')->getMock())); // mock sender to resolve promise with the given $response in response to the given $request $sender = $this->makeSenderMock(); $sender->expects($this->once())->method('send')->with($this->equalTo($request))->willReturn(Promise\resolve($response)); - $transaction = new Transaction($sender, $messageFactory, $loop); + $transaction = new Transaction($sender, $loop); $transaction = $transaction->withOptions(array('streaming' => true, 'timeout' => -1)); $promise = $transaction->send($request); @@ -504,16 +475,15 @@ public function testReceivingStreamingBodyWillResolveWithStreamingResponseIfStre public function testResponseCode304WithoutLocationWillResolveWithResponseAsIs() { - $messageFactory = new MessageFactory(); $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); // conditional GET request will respond with 304 (Not Modified - $request = $messageFactory->request('GET', 'http://example.com', array('If-None-Match' => '"abc"')); - $response = $messageFactory->response(1.0, 304, null, array('ETag' => '"abc"')); + $request = new Request('GET', 'http://example.com', array('If-None-Match' => '"abc"')); + $response = new Response(304, array('ETag' => '"abc"')); $sender = $this->makeSenderMock(); $sender->expects($this->once())->method('send')->with($request)->willReturn(Promise\resolve($response)); - $transaction = new Transaction($sender, $messageFactory, $loop); + $transaction = new Transaction($sender, $loop); $transaction = $transaction->withOptions(array('timeout' => -1)); $promise = $transaction->send($request); @@ -522,12 +492,11 @@ public function testResponseCode304WithoutLocationWillResolveWithResponseAsIs() public function testCustomRedirectResponseCode333WillFollowLocationHeaderAndSendRedirectedRequest() { - $messageFactory = new MessageFactory(); $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); // original GET request will respond with custom 333 redirect status code and follow location header - $requestOriginal = $messageFactory->request('GET', 'http://example.com'); - $response = $messageFactory->response(1.0, 333, null, array('Location' => 'foo')); + $requestOriginal = new Request('GET', 'http://example.com'); + $response = new Response(333, array('Location' => 'foo')); $sender = $this->makeSenderMock(); $sender->expects($this->exactly(2))->method('send')->withConsecutive( array($requestOriginal), @@ -539,27 +508,26 @@ public function testCustomRedirectResponseCode333WillFollowLocationHeaderAndSend new \React\Promise\Promise(function () { }) ); - $transaction = new Transaction($sender, $messageFactory, $loop); + $transaction = new Transaction($sender, $loop); $transaction->send($requestOriginal); } public function testFollowingRedirectWithSpecifiedHeaders() { - $messageFactory = new MessageFactory(); $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); $customHeaders = array('User-Agent' => 'Chrome'); - $requestWithUserAgent = $messageFactory->request('GET', 'http://example.com', $customHeaders); + $requestWithUserAgent = new Request('GET', 'http://example.com', $customHeaders); $sender = $this->makeSenderMock(); // mock sender to resolve promise with the given $redirectResponse in // response to the given $requestWithUserAgent - $redirectResponse = $messageFactory->response(1.0, 301, null, array('Location' => 'http://redirect.com')); + $redirectResponse = new Response(301, array('Location' => 'http://redirect.com')); $sender->expects($this->at(0))->method('send')->willReturn(Promise\resolve($redirectResponse)); // mock sender to resolve promise with the given $okResponse in // response to the given $requestWithUserAgent - $okResponse = $messageFactory->response(1.0, 200, 'OK'); + $okResponse = new Response(200); $that = $this; $sender->expects($this->at(1)) ->method('send') @@ -568,27 +536,26 @@ public function testFollowingRedirectWithSpecifiedHeaders() return true; }))->willReturn(Promise\resolve($okResponse)); - $transaction = new Transaction($sender, $messageFactory, $loop); + $transaction = new Transaction($sender, $loop); $transaction->send($requestWithUserAgent); } public function testRemovingAuthorizationHeaderWhenChangingHostnamesDuringRedirect() { - $messageFactory = new MessageFactory(); $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); $customHeaders = array('Authorization' => 'secret'); - $requestWithAuthorization = $messageFactory->request('GET', 'http://example.com', $customHeaders); + $requestWithAuthorization = new Request('GET', 'http://example.com', $customHeaders); $sender = $this->makeSenderMock(); // mock sender to resolve promise with the given $redirectResponse in // response to the given $requestWithAuthorization - $redirectResponse = $messageFactory->response(1.0, 301, null, array('Location' => 'http://redirect.com')); + $redirectResponse = new Response(301, array('Location' => 'http://redirect.com')); $sender->expects($this->at(0))->method('send')->willReturn(Promise\resolve($redirectResponse)); // mock sender to resolve promise with the given $okResponse in // response to the given $requestWithAuthorization - $okResponse = $messageFactory->response(1.0, 200, 'OK'); + $okResponse = new Response(200); $that = $this; $sender->expects($this->at(1)) ->method('send') @@ -597,27 +564,26 @@ public function testRemovingAuthorizationHeaderWhenChangingHostnamesDuringRedire return true; }))->willReturn(Promise\resolve($okResponse)); - $transaction = new Transaction($sender, $messageFactory, $loop); + $transaction = new Transaction($sender, $loop); $transaction->send($requestWithAuthorization); } public function testAuthorizationHeaderIsForwardedWhenRedirectingToSameDomain() { - $messageFactory = new MessageFactory(); $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); $customHeaders = array('Authorization' => 'secret'); - $requestWithAuthorization = $messageFactory->request('GET', 'http://example.com', $customHeaders); + $requestWithAuthorization = new Request('GET', 'http://example.com', $customHeaders); $sender = $this->makeSenderMock(); // mock sender to resolve promise with the given $redirectResponse in // response to the given $requestWithAuthorization - $redirectResponse = $messageFactory->response(1.0, 301, null, array('Location' => 'http://example.com/new')); + $redirectResponse = new Response(301, array('Location' => 'http://example.com/new')); $sender->expects($this->at(0))->method('send')->willReturn(Promise\resolve($redirectResponse)); // mock sender to resolve promise with the given $okResponse in // response to the given $requestWithAuthorization - $okResponse = $messageFactory->response(1.0, 200, 'OK'); + $okResponse = new Response(200); $that = $this; $sender->expects($this->at(1)) ->method('send') @@ -626,26 +592,25 @@ public function testAuthorizationHeaderIsForwardedWhenRedirectingToSameDomain() return true; }))->willReturn(Promise\resolve($okResponse)); - $transaction = new Transaction($sender, $messageFactory, $loop); + $transaction = new Transaction($sender, $loop); $transaction->send($requestWithAuthorization); } public function testAuthorizationHeaderIsForwardedWhenLocationContainsAuthentication() { - $messageFactory = new MessageFactory(); $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); - $request = $messageFactory->request('GET', 'http://example.com'); + $request = new Request('GET', 'http://example.com'); $sender = $this->makeSenderMock(); // mock sender to resolve promise with the given $redirectResponse in // response to the given $requestWithAuthorization - $redirectResponse = $messageFactory->response(1.0, 301, null, array('Location' => 'http://user:pass@example.com/new')); + $redirectResponse = new Response(301, array('Location' => 'http://user:pass@example.com/new')); $sender->expects($this->at(0))->method('send')->willReturn(Promise\resolve($redirectResponse)); // mock sender to resolve promise with the given $okResponse in // response to the given $requestWithAuthorization - $okResponse = $messageFactory->response(1.0, 200, 'OK'); + $okResponse = new Response(200); $that = $this; $sender->expects($this->at(1)) ->method('send') @@ -655,13 +620,12 @@ public function testAuthorizationHeaderIsForwardedWhenLocationContainsAuthentica return true; }))->willReturn(Promise\resolve($okResponse)); - $transaction = new Transaction($sender, $messageFactory, $loop); + $transaction = new Transaction($sender, $loop); $transaction->send($request); } public function testSomeRequestHeadersShouldBeRemovedWhenRedirecting() { - $messageFactory = new MessageFactory(); $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); $customHeaders = array( @@ -669,17 +633,17 @@ public function testSomeRequestHeadersShouldBeRemovedWhenRedirecting() 'Content-Length' => '111', ); - $requestWithCustomHeaders = $messageFactory->request('GET', 'http://example.com', $customHeaders); + $requestWithCustomHeaders = new Request('GET', 'http://example.com', $customHeaders); $sender = $this->makeSenderMock(); // mock sender to resolve promise with the given $redirectResponse in // response to the given $requestWithCustomHeaders - $redirectResponse = $messageFactory->response(1.0, 301, null, array('Location' => 'http://example.com/new')); + $redirectResponse = new Response(301, array('Location' => 'http://example.com/new')); $sender->expects($this->at(0))->method('send')->willReturn(Promise\resolve($redirectResponse)); // mock sender to resolve promise with the given $okResponse in // response to the given $requestWithCustomHeaders - $okResponse = $messageFactory->response(1.0, 200, 'OK'); + $okResponse = new Response(200); $that = $this; $sender->expects($this->at(1)) ->method('send') @@ -689,16 +653,15 @@ public function testSomeRequestHeadersShouldBeRemovedWhenRedirecting() return true; }))->willReturn(Promise\resolve($okResponse)); - $transaction = new Transaction($sender, $messageFactory, $loop); + $transaction = new Transaction($sender, $loop); $transaction->send($requestWithCustomHeaders); } public function testCancelTransactionWillCancelRequest() { - $messageFactory = new MessageFactory(); $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); - $request = $messageFactory->request('GET', 'http://example.com'); + $request = new Request('GET', 'http://example.com'); $sender = $this->makeSenderMock(); $pending = new \React\Promise\Promise(function () { }, $this->expectCallableOnce()); @@ -706,7 +669,7 @@ public function testCancelTransactionWillCancelRequest() // mock sender to return pending promise which should be cancelled when cancelling result $sender->expects($this->once())->method('send')->willReturn($pending); - $transaction = new Transaction($sender, $messageFactory, $loop); + $transaction = new Transaction($sender, $loop); $promise = $transaction->send($request); $promise->cancel(); @@ -714,14 +677,12 @@ public function testCancelTransactionWillCancelRequest() public function testCancelTransactionWillCancelTimeoutTimer() { - $messageFactory = new MessageFactory(); - $timer = $this->getMockBuilder('React\EventLoop\TimerInterface')->getMock(); $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); $loop->expects($this->once())->method('addTimer')->willReturn($timer); $loop->expects($this->once())->method('cancelTimer')->with($timer); - $request = $messageFactory->request('GET', 'http://example.com'); + $request = new Request('GET', 'http://example.com'); $sender = $this->makeSenderMock(); $pending = new \React\Promise\Promise(function () { }, function () { throw new \RuntimeException(); }); @@ -729,7 +690,7 @@ public function testCancelTransactionWillCancelTimeoutTimer() // mock sender to return pending promise which should be cancelled when cancelling result $sender->expects($this->once())->method('send')->willReturn($pending); - $transaction = new Transaction($sender, $messageFactory, $loop); + $transaction = new Transaction($sender, $loop); $transaction = $transaction->withOptions(array('timeout' => 2)); $promise = $transaction->send($request); @@ -738,14 +699,13 @@ public function testCancelTransactionWillCancelTimeoutTimer() public function testCancelTransactionWillCancelRedirectedRequest() { - $messageFactory = new MessageFactory(); $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); - $request = $messageFactory->request('GET', 'http://example.com'); + $request = new Request('GET', 'http://example.com'); $sender = $this->makeSenderMock(); // mock sender to resolve promise with the given $redirectResponse in - $redirectResponse = $messageFactory->response(1.0, 301, null, array('Location' => 'http://example.com/new')); + $redirectResponse = new Response(301, array('Location' => 'http://example.com/new')); $sender->expects($this->at(0))->method('send')->willReturn(Promise\resolve($redirectResponse)); $pending = new \React\Promise\Promise(function () { }, $this->expectCallableOnce()); @@ -753,7 +713,7 @@ public function testCancelTransactionWillCancelRedirectedRequest() // mock sender to return pending promise which should be cancelled when cancelling result $sender->expects($this->at(1))->method('send')->willReturn($pending); - $transaction = new Transaction($sender, $messageFactory, $loop); + $transaction = new Transaction($sender, $loop); $promise = $transaction->send($request); $promise->cancel(); @@ -761,10 +721,9 @@ public function testCancelTransactionWillCancelRedirectedRequest() public function testCancelTransactionWillCancelRedirectedRequestAgain() { - $messageFactory = new MessageFactory(); $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); - $request = $messageFactory->request('GET', 'http://example.com'); + $request = new Request('GET', 'http://example.com'); $sender = $this->makeSenderMock(); // mock sender to resolve promise with the given $redirectResponse in @@ -776,31 +735,30 @@ public function testCancelTransactionWillCancelRedirectedRequestAgain() // mock sender to return pending promise which should be cancelled when cancelling result $sender->expects($this->at(1))->method('send')->willReturn($second); - $transaction = new Transaction($sender, $messageFactory, $loop); + $transaction = new Transaction($sender, $loop); $promise = $transaction->send($request); // mock sender to resolve promise with the given $redirectResponse in - $first->resolve($messageFactory->response(1.0, 301, null, array('Location' => 'http://example.com/new'))); + $first->resolve(new Response(301, array('Location' => 'http://example.com/new'))); $promise->cancel(); } public function testCancelTransactionWillCloseBufferingStream() { - $messageFactory = new MessageFactory(); $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); - $request = $messageFactory->request('GET', 'http://example.com'); + $request = new Request('GET', 'http://example.com'); $sender = $this->makeSenderMock(); $body = new ThroughStream(); $body->on('close', $this->expectCallableOnce()); // mock sender to resolve promise with the given $redirectResponse in - $redirectResponse = $messageFactory->response(1.0, 301, null, array('Location' => 'http://example.com/new'), $body); + $redirectResponse = new Response(301, array('Location' => 'http://example.com/new'), new ReadableBodyStream($body)); $sender->expects($this->once())->method('send')->willReturn(Promise\resolve($redirectResponse)); - $transaction = new Transaction($sender, $messageFactory, $loop); + $transaction = new Transaction($sender, $loop); $promise = $transaction->send($request); $promise->cancel(); @@ -808,36 +766,34 @@ public function testCancelTransactionWillCloseBufferingStream() public function testCancelTransactionWillCloseBufferingStreamAgain() { - $messageFactory = new MessageFactory(); $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); - $request = $messageFactory->request('GET', 'http://example.com'); + $request = new Request('GET', 'http://example.com'); $sender = $this->makeSenderMock(); $first = new Deferred(); $sender->expects($this->once())->method('send')->willReturn($first->promise()); - $transaction = new Transaction($sender, $messageFactory, $loop); + $transaction = new Transaction($sender, $loop); $promise = $transaction->send($request); $body = new ThroughStream(); $body->on('close', $this->expectCallableOnce()); // mock sender to resolve promise with the given $redirectResponse in - $first->resolve($messageFactory->response(1.0, 301, null, array('Location' => 'http://example.com/new'), $body)); + $first->resolve(new Response(301, array('Location' => 'http://example.com/new'), new ReadableBodyStream($body))); $promise->cancel(); } public function testCancelTransactionShouldCancelSendingPromise() { - $messageFactory = new MessageFactory(); $loop = $this->getMockBuilder('React\EventLoop\LoopInterface')->getMock(); - $request = $messageFactory->request('GET', 'http://example.com'); + $request = new Request('GET', 'http://example.com'); $sender = $this->makeSenderMock(); // mock sender to resolve promise with the given $redirectResponse in - $redirectResponse = $messageFactory->response(1.0, 301, null, array('Location' => 'http://example.com/new')); + $redirectResponse = new Response(301, array('Location' => 'http://example.com/new')); $sender->expects($this->at(0))->method('send')->willReturn(Promise\resolve($redirectResponse)); $pending = new \React\Promise\Promise(function () { }, $this->expectCallableOnce()); @@ -845,7 +801,7 @@ public function testCancelTransactionShouldCancelSendingPromise() // mock sender to return pending promise which should be cancelled when cancelling result $sender->expects($this->at(1))->method('send')->willReturn($pending); - $transaction = new Transaction($sender, $messageFactory, $loop); + $transaction = new Transaction($sender, $loop); $promise = $transaction->send($request); $promise->cancel();