Do not attempt to rewind unsociable streams when transmitting response

This commit is contained in:
PJ Dietz 2016-02-22 14:45:16 -05:00
parent db7aaa2688
commit 0c61641376
3 changed files with 43 additions and 2 deletions

1
.gitignore vendored
View File

@ -21,6 +21,7 @@ preview
workspace.xml
# Vagrant
.bundle/
.vagrant/
# Vagrant sandbox site files.

View File

@ -98,7 +98,9 @@ class Transmitter implements TransmitterInterface
private function outputBody(StreamInterface $body)
{
if ($this->chunkSize > 0) {
$body->rewind();
if ($body->isSeekable()) {
$body->rewind();
}
while (!$body->eof()) {
print $body->read($this->chunkSize);
}

View File

@ -135,6 +135,7 @@ class TransmitterTest extends \PHPUnit_Framework_TestCase
$chunkSize = 3;
$position = 0;
$this->body->isSeekable()->willReturn(true);
$this->body->isReadable()->willReturn(true);
$this->body->rewind()->willReturn(true);
$this->body->eof()->willReturn(false);
@ -154,13 +155,50 @@ class TransmitterTest extends \PHPUnit_Framework_TestCase
$transmitter->setChunkSize($chunkSize);
ob_start();
$transmitter->transmit($this->request->reveal(), $this->response->reveal(), $chunkSize);
$transmitter->transmit($this->request->reveal(), $this->response->reveal());
$captured = ob_get_contents();
ob_end_clean();
$this->assertEquals($content, $captured);
}
/**
* @covers ::transmit
* @covers ::setChunkSize
* @covers ::outputBody
*/
public function testOutputsUnseekableStreamInChunks()
{
$content = "Hello, world!";
$chunkSize = 3;
$position = 0;
$this->body->isSeekable()->willReturn(false);
$this->body->isReadable()->willReturn(true);
$this->body->rewind()->willThrow(new \RuntimeException());
$this->body->eof()->willReturn(false);
$this->body->read(Argument::any())->will(
function ($args) use ($content, &$position) {
$chunkSize = $args[0];
$chunk = substr($content, $position, $chunkSize);
$position += $chunkSize;
if ($position >= strlen($content)) {
$this->eof()->willReturn(true);
}
return $chunk;
}
);
$transmitter = new Transmitter();
$transmitter->setChunkSize($chunkSize);
ob_start();
$transmitter->transmit($this->request->reveal(), $this->response->reveal());
$captured = ob_get_contents();
ob_end_clean();
$this->assertEquals($content, $captured);
}
// ------------------------------------------------------------------------
// Preparation