3 * @see https://github.com/zendframework/zend-diactoros for the canonical source repository
4 * @copyright Copyright (c) 2015-2018 Zend Technologies USA Inc. (http://www.zend.com)
5 * @license https://github.com/zendframework/zend-diactoros/blob/master/LICENSE.md New BSD License
8 namespace Zend\Diactoros\Response;
10 use Psr\Http\Message\ResponseInterface;
12 use function is_array;
13 use function preg_match;
18 * @deprecated since 1.8.0. The package zendframework/zend-httphandlerrunner
19 * now provides this functionality.
21 class SapiStreamEmitter implements EmitterInterface
26 * Emits a response for a PHP SAPI environment.
28 * Emits the status line and headers via the header() function, and the
29 * body content via the output buffer.
31 * @param ResponseInterface $response
32 * @param int $maxBufferLength Maximum output buffering size for each iteration
34 public function emit(ResponseInterface $response, $maxBufferLength = 8192)
36 $this->assertNoPreviousOutput();
37 $this->emitHeaders($response);
38 $this->emitStatusLine($response);
40 $range = $this->parseContentRange($response->getHeaderLine('Content-Range'));
42 if (is_array($range) && $range[0] === 'bytes') {
43 $this->emitBodyRange($range, $response, $maxBufferLength);
47 $this->emitBody($response, $maxBufferLength);
51 * Emit the message body.
53 * @param ResponseInterface $response
54 * @param int $maxBufferLength
56 private function emitBody(ResponseInterface $response, $maxBufferLength)
58 $body = $response->getBody();
60 if ($body->isSeekable()) {
64 if (! $body->isReadable()) {
69 while (! $body->eof()) {
70 echo $body->read($maxBufferLength);
75 * Emit a range of the message body.
78 * @param ResponseInterface $response
79 * @param int $maxBufferLength
81 private function emitBodyRange(array $range, ResponseInterface $response, $maxBufferLength)
83 list($unit, $first, $last, $length) = $range;
85 $body = $response->getBody();
87 $length = $last - $first + 1;
89 if ($body->isSeekable()) {
95 if (! $body->isReadable()) {
96 echo substr($body->getContents(), $first, $length);
100 $remaining = $length;
102 while ($remaining >= $maxBufferLength && ! $body->eof()) {
103 $contents = $body->read($maxBufferLength);
104 $remaining -= strlen($contents);
109 if ($remaining > 0 && ! $body->eof()) {
110 echo $body->read($remaining);
115 * Parse content-range header
116 * http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.16
118 * @param string $header
119 * @return false|array [unit, first, last, length]; returns false if no
120 * content range or an invalid content range is provided
122 private function parseContentRange($header)
124 if (preg_match('/(?P<unit>[\w]+)\s+(?P<first>\d+)-(?P<last>\d+)\/(?P<length>\d+|\*)/', $header, $matches)) {
127 (int) $matches['first'],
128 (int) $matches['last'],
129 $matches['length'] === '*' ? '*' : (int) $matches['length'],