This method may be repeatedly called to stream the response body.
Applications that can afford to buffer an entire response in memory or
can wait for all body data to generate may use Response::end() to output
the entire response in a single call.
Note: Headers are sent upon the first invocation of Response::stream().
private function sendMultiRange($handle, Response $response, $fileInfo, $range) : \Generator { foreach ($range->ranges as list($startPos, $endPos)) { $header = sprintf("--%s\r\nContent-Type: %s\r\nContent-Range: bytes %d-%d/%d\r\n\r\n", $range->boundary, $range->contentType, $startPos, $endPos, $fileInfo->size); $response->stream($header); yield from $this->sendSingleRange($handle, $response, $startPos, $endPos); $response->stream("\r\n"); } $response->stream("--{$range->boundary}--"); }
public function __invoke(Request $req, Response $res) { $headers = $req->getAllHeaders(); unset($headers["accept-encoding"]); $connection = $headers["connection"]; unset($headers["connection"]); foreach ($connection as $value) { foreach (explode(",", strtolower($value)) as $type) { $type = trim($type); if ($type == "upgrade") { $headers["connection"][0] = "upgrade"; } else { unset($headers[$type]); } } } if ($this->headers) { if (is_callable($this->headers)) { $headers = ($this->headers)($headers); } else { $headers = $this->headers + $headers; } } $promise = $this->client->request((new \Amp\Artax\Request())->setMethod($req->getMethod())->setUri($this->target . $req->getUri())->setAllHeaders($headers)->setBody((yield $req->getBody()))); // no async sending possible :-( [because of redirects] $promise->watch(function ($update) use($req, $res, &$hasBody, &$status, &$zlib) { list($type, $data) = $update; if ($type == Notify::RESPONSE_HEADERS) { $headers = array_change_key_case($data["headers"], CASE_LOWER); foreach ($data["headers"] as $header => $values) { foreach ($values as $value) { $res->addHeader($header, $value); } } $res->setStatus($status = $data["status"]); $res->setReason($data["reason"]); if (isset($headers["content-encoding"]) && strcasecmp(trim(current($headers["content-encoding"])), 'gzip') === 0) { $zlib = inflate_init(ZLIB_ENCODING_GZIP); } $hasBody = true; } if ($type == Notify::RESPONSE_BODY_DATA) { if ($zlib) { $data = inflate_add($zlib, $data); } $res->stream($data); } if ($type == Notify::RESPONSE) { if (!$hasBody) { foreach ($data->getAllHeaders() as $header => $values) { foreach ($values as $value) { $res->addHeader($header, $value); } } $res->setStatus($status = $data->getStatus()); $res->setReason($data->getReason()); } if ($status == 101) { $req->setLocalVar("aerys.reverse.socket", $update["export_socket"]()); } $res->end($zlib ? inflate_add("", ZLIB_FINISH) : null); } }); (yield $promise); }