Skip to content
This repository has been archived by the owner on Jan 30, 2020. It is now read-only.

Commit

Permalink
\Http\Response\Stream honoring the Content-Length header
Browse files Browse the repository at this point in the history
  • Loading branch information
Duccio Gasparri committed May 29, 2012
1 parent 27d50b0 commit 9cc7538
Showing 1 changed file with 119 additions and 36 deletions.
155 changes: 119 additions & 36 deletions src/Response/Stream.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@

namespace Zend\Http\Response;

use Zend\Http\Response;
use Zend\Http\Response,
Zend\Http\Exception;


/**
* Zend_Http_Response represents an HTTP 1.0 / 1.1 response message. It
Expand All @@ -35,6 +37,21 @@
*/
class Stream extends Response
{

/**
* The Content-Length value, if set
*
* @var int
*/
protected $contentLength = null;

/**
* The portion of the body that has alredy been streamed
*
* @var int
*/
protected $contentStreamed = 0;

/**
* Response as stream
*
Expand All @@ -56,7 +73,7 @@ class Stream extends Response
*
* @var boolean
*/
protected $_cleanup;
protected $cleanup;

/**
* Get the response as stream
Expand Down Expand Up @@ -87,7 +104,7 @@ public function setStream($stream)
*/
public function getCleanup()
{
return $this->_cleanup;
return $this->cleanup;
}

/**
Expand All @@ -97,7 +114,7 @@ public function getCleanup()
*/
public function setCleanup($cleanup = true)
{
$this->_cleanup = $cleanup;
$this->cleanup = $cleanup;
}

/**
Expand All @@ -122,24 +139,79 @@ public function setStreamName($streamName)
return $this;
}

/**
* Create a new Zend\Http\Response\Stream object from a string

/**
* Create a new Zend\Http\Response\Stream object from a stream
*
* @param string $responseString
* @param resource $stream
* @return Stream
*/
public static function fromStream($responseString, $stream)
{
* @param string $responseString
* @param resource $stream
* @return Stream
*/
public static function fromStream($responseString, $stream)
{

if (!is_resource($stream)) {
throw new Exception\InvalidArgumentException('A valid stream is required');
}

$response = static::fromString($responseString);
if (is_resource($stream)) {
$response->setStream($stream);
}
$headerComplete = false;
$headersString = '';

$responseArray = explode("\n",$responseString);

return $response;
while (count($responseArray)) {
$nextLine = array_shift($responseArray);
$headersString .= $nextLine."\n";
$nextLineTrimmed = trim($nextLine);
if ($nextLineTrimmed == "") {
$headerComplete = true;
break;
}

}

if (!$headerComplete) {
while (false !== ($nextLine = fgets($stream))) {

$headersString .= trim($nextLine)."\r\n";
if ($nextLine == "\r\n" || $nextLine == "\n") {
$headerComplete = true;
break;
}
}
}

if (!$headerComplete) {
throw new Exception\OutOfRangeException('End of header not found');
}

$response = static::fromString($headersString);

if (is_resource($stream)) {
$response->setStream($stream);
}

if (count($responseArray)) {
$response->content = implode("\n", $responseArray);
}

$headers = $response->headers();
foreach($headers as $header) {
if ($header instanceof \Zend\Http\Header\ContentLength) {
$response->contentLength = (int) $header->getFieldValue();
if (strlen($response->content) > $response->contentLength) {
throw new Exception\OutOfRangeException(
sprintf('Too much content was extracted from the stream (%d instead of %d bytes)',
strlen($this->content), $this->contentLength));
}
break;
}
}

return $response;
}



/**
* Get the response body as string
*
Expand Down Expand Up @@ -176,23 +248,34 @@ public function getRawBody()
return $this->content;
}

/**
* Read stream content and return it as string
*
* Function reads the remainder of the body from the stream and closes the stream.
*
* @return string
*/
protected function readStream()
{
if (!is_resource($this->stream)) {
return '';
}

$this->content .= stream_get_contents($this->stream);
$this->stream = null; //Could be listened by others
}


/**
* Read stream content and return it as string
*
* Function reads the remainder of the body from the stream and closes the stream.
*
* @return string
*/
protected function readStream()
{
if (!is_null($this->contentLength)) {
$bytes = $this->contentLength - $this->contentStreamed;
} else {
$bytes = -1; //Read the whole buffer
}

if (!is_resource($this->stream) || $bytes == 0) {
return '';
}

$this->content .= stream_get_contents($this->stream, $bytes);
$this->contentStreamed += strlen($this->content);

if ($this->contentLength == $this->contentStreamed) {
$this->stream = null;
}
}

/**
* Destructor
*/
Expand All @@ -201,7 +284,7 @@ public function __destruct()
if (is_resource($this->stream)) {
$this->stream = null; //Could be listened by others
}
if ($this->_cleanup) {
if ($this->cleanup) {
@unlink($this->stream_name);
}
}
Expand Down

0 comments on commit 9cc7538

Please sign in to comment.