/** * Returns a readable JSON stream for the given ResponseInterface * * @param PromiseInterface $promise Promise<ResponseInterface> * @return ReadableStreamInterface * @uses self::parsePlainSream() */ public function parseJsonStream(PromiseInterface $promise) { // application/json $in = $this->parsePlainStream($promise); $out = new ReadableStream(); // invalid/closing input stream => return closed output stream if (!$in->isReadable()) { $out->close(); return $out; } // forward each data chunk to the streaming JSON parser $parser = new StreamingJsonParser(); $in->on('data', function ($data) use($parser, $out) { $objects = $parser->push($data); foreach ($objects as $object) { if (isset($object['error'])) { $out->emit('error', array(new JsonProgressException($object), $out)); $out->close(); return; } $out->emit('progress', array($object, $out)); } }); // forward error and make sure stream closes $in->on('error', function ($error) use($out) { $out->emit('error', array($error, $out)); $out->close(); }); // closing either stream closes the other one $in->on('close', array($out, 'close')); $out->on('close', array($in, 'close')); return $out; }
public function parsePlainStream(PromiseInterface $promise) { // text/plain $out = new ReadableStream(); // try to cancel promise once the stream closes if ($promise instanceof CancellablePromiseInterface) { $out->on('close', function () use($promise) { $promise->cancel(); }); } $promise->then(function ($response) use($out) { $out->close(); }, function ($error) use($out) { $out->emit('error', array($error, $out)); $out->close(); }, function ($progress) use($out) { if (is_array($progress) && isset($progress['responseStream'])) { $stream = $progress['responseStream']; /* @var $stream React\Stream\Stream */ // hack to do not buffer stream contents in body $stream->removeAllListeners('data'); // got a streaming HTTP response => forward each data chunk to the resulting output stream $stream->on('data', function ($data) use($out) { $out->emit('data', array($data, $out)); }); } }); return $out; }
/** @test */ public function doubleCloseShouldWork() { $readable = new ReadableStream(); $readable->close(); $readable->close(); $this->assertFalse($readable->isReadable()); }
public function testClosedReadableStreamRejects() { $stream = new ReadableStream(); $stream->close(); $promise = Stream\first($stream); $this->expectPromiseReject($promise); }
public function testClosedStreamResolvesWithEmptyBuffer() { $stream = new ReadableStream(); $stream->close(); $promise = Stream\all($stream); $this->expectPromiseResolveWith(array(), $promise); }
public function testReturnsStreamThatWillBeClosedWhenPromiseResolvesWithClosedInputStream() { $input = new ReadableStream(); $input->close(); $promise = Timer\resolve(0.001, $this->loop)->then(function () use($input) { return $input; }); $stream = Stream\unwrapReadable($promise); $this->assertTrue($stream->isReadable()); $stream->on('close', $this->expectCallableOnce()); $this->loop->run(); $this->assertFalse($stream->isReadable()); }
public function testReceivingStreamingBodyWillResolveWithBufferedResponseByDefault() { $messageFactory = new MessageFactory(); $loop = Factory::create(); $stream = new ReadableStream(); $loop->addTimer(0.001, function () use($stream) { $stream->emit('data', array('hello world')); $stream->close(); }); $request = $this->getMock('Psr\\Http\\Message\\RequestInterface'); $response = $messageFactory->response(1.0, 200, 'OK', array(), $stream); // mock sender to resolve promise with the given $response in response to the given $request $sender = $this->getMockBuilder('Clue\\React\\Buzz\\Io\\Sender')->disableOriginalConstructor()->getMock(); $sender->expects($this->once())->method('send')->with($this->equalTo($request))->willReturn(Promise\resolve($response)); $transaction = new Transaction($request, $sender, array(), $messageFactory); $promise = $transaction->send(); $response = Block\await($promise, $loop); $this->assertEquals(200, $response->getStatusCode()); $this->assertEquals('hello world', (string) $response->getBody()); }
/** @test */ public function pipeShouldSucceedAndResolve() { $callback = $this->expectCallableOnceWith('foobar'); $sink = new BufferedSink(); $sink->promise()->then($callback); $readable = new ReadableStream(); $readable->pipe($sink); $readable->emit(Event::DATA, array('foo')); $readable->emit(Event::DATA, array('bar')); $readable->close(); }
public function testPostStreamClosed() { $stream = new ReadableStream(); $stream->close(); $response = Block\await($this->browser->post($this->base . 'post', array(), $stream), $this->loop); $data = json_decode((string) $response->getBody(), true); $this->assertEquals('', $data['data']); }