Chris@0: assertNoPreviousOutput(); Chris@12: $this->emitHeaders($response); Chris@0: $this->emitStatusLine($response); Chris@0: Chris@0: $range = $this->parseContentRange($response->getHeaderLine('Content-Range')); Chris@0: Chris@0: if (is_array($range) && $range[0] === 'bytes') { Chris@0: $this->emitBodyRange($range, $response, $maxBufferLength); Chris@0: return; Chris@0: } Chris@0: Chris@0: $this->emitBody($response, $maxBufferLength); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Emit the message body. Chris@0: * Chris@0: * @param ResponseInterface $response Chris@0: * @param int $maxBufferLength Chris@0: */ Chris@0: private function emitBody(ResponseInterface $response, $maxBufferLength) Chris@0: { Chris@0: $body = $response->getBody(); Chris@0: Chris@0: if ($body->isSeekable()) { Chris@0: $body->rewind(); Chris@0: } Chris@0: Chris@0: if (! $body->isReadable()) { Chris@0: echo $body; Chris@0: return; Chris@0: } Chris@0: Chris@0: while (! $body->eof()) { Chris@0: echo $body->read($maxBufferLength); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Emit a range of the message body. Chris@0: * Chris@0: * @param array $range Chris@0: * @param ResponseInterface $response Chris@0: * @param int $maxBufferLength Chris@0: */ Chris@0: private function emitBodyRange(array $range, ResponseInterface $response, $maxBufferLength) Chris@0: { Chris@0: list($unit, $first, $last, $length) = $range; Chris@0: Chris@0: $body = $response->getBody(); Chris@0: Chris@0: $length = $last - $first + 1; Chris@0: Chris@0: if ($body->isSeekable()) { Chris@0: $body->seek($first); Chris@0: Chris@0: $first = 0; Chris@0: } Chris@0: Chris@0: if (! $body->isReadable()) { Chris@0: echo substr($body->getContents(), $first, $length); Chris@0: return; Chris@0: } Chris@0: Chris@0: $remaining = $length; Chris@0: Chris@0: while ($remaining >= $maxBufferLength && ! $body->eof()) { Chris@0: $contents = $body->read($maxBufferLength); Chris@0: $remaining -= strlen($contents); Chris@0: Chris@0: echo $contents; Chris@0: } Chris@0: Chris@0: if ($remaining > 0 && ! $body->eof()) { Chris@0: echo $body->read($remaining); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Parse content-range header Chris@0: * http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.16 Chris@0: * Chris@0: * @param string $header Chris@0: * @return false|array [unit, first, last, length]; returns false if no Chris@0: * content range or an invalid content range is provided Chris@0: */ Chris@0: private function parseContentRange($header) Chris@0: { Chris@0: if (preg_match('/(?P[\w]+)\s+(?P\d+)-(?P\d+)\/(?P\d+|\*)/', $header, $matches)) { Chris@0: return [ Chris@0: $matches['unit'], Chris@0: (int) $matches['first'], Chris@0: (int) $matches['last'], Chris@0: $matches['length'] === '*' ? '*' : (int) $matches['length'], Chris@0: ]; Chris@0: } Chris@0: return false; Chris@0: } Chris@0: }