/**
  * Read next chunk from temp file.
  * 
  * Fall back to reading from buffered source stream if contents of the temp file have been read.
  */
 protected function readNextChunk() : \Generator
 {
     $chunk = (yield $this->stream->readBuffer($this->bufferSize));
     if ($chunk === null) {
         $chunk = (yield $this->source->readBuffer($this->bufferSize));
         if ($chunk === null) {
             $this->body->computeSize();
             $this->source->close();
         } else {
             $this->body->incrementOffset((yield $this->stream->write($chunk)));
         }
         $chunk = (yield $this->stream->readBuffer($this->bufferSize));
     }
     return $chunk;
 }
Beispiel #2
0
 protected function sendRequest(SocketStream $socket, HttpRequest $request, int &$sent) : \Generator
 {
     $request = $this->normalizeRequest($request);
     $body = $request->getBody();
     $size = (yield $body->getSize());
     $sendfile = false;
     if ($body instanceof FileBody && $socket->isSendfileSupported()) {
         $sendfile = true;
         $chunk = $size ? '' : null;
     } else {
         if ($request->getProtocolVersion() == '1.0' && $size === null) {
             if (!$body->isCached()) {
                 $body = new BufferedBody((yield $body->getReadableStream()));
             }
             (yield $body->discard());
             $size = (yield $body->getSize());
         }
         $bodyStream = (yield $body->getReadableStream());
         $clen = $size === null ? 4089 : 4096;
         $chunk = (yield $bodyStream->readBuffer($clen));
         $len = \strlen($chunk ?? '');
         if ($chunk === null) {
             $size = 0;
         } elseif ($len < $clen) {
             $size = $len;
         }
     }
     $buffer = $this->serializeHeaders($request, $size);
     $expect = false;
     if ($this->expectContinue && $chunk !== null && $request->getProtocolVersion() == '1.1') {
         $expect = true;
         $buffer .= "Expect: 100-continue\r\n";
     }
     (yield $socket->write($buffer . "\r\n"));
     (yield $socket->flush());
     if ($expect) {
         if (!\preg_match("'^HTTP/1\\.1\\s+100(?:\$|\\s)'i", $line = (yield $socket->readLine()))) {
             try {
                 return $line;
             } finally {
                 if (isset($bodyStream)) {
                     $bodyStream->close();
                 }
             }
         }
     }
     if ($sendfile) {
         if ($size) {
             $sent += (yield LoopConfig::currentFilesystem()->sendfile($body->getFile(), $socket->getSocket(), $size));
         }
     } elseif ($size === null) {
         $sent += (yield $socket->write(\dechex($len) . "\r\n" . $chunk . "\r\n"));
         if ($len === $clen) {
             // Align each chunk with length and line breaks to fit into 4 KB payload.
             $sent += (yield new CopyBytes($bodyStream, $socket, true, null, 4089, function (string $chunk) {
                 return \dechex(\strlen($chunk)) . "\r\n" . $chunk . "\r\n";
             }));
         }
         (yield $socket->write("0\r\n\r\n"));
     } elseif ($size > 0) {
         $sent += (yield $socket->write($chunk));
         if ($len === $clen) {
             $sent += (yield new CopyBytes($bodyStream, $socket, true, $size - $len));
         }
     }
     (yield $socket->flush());
 }