示例#1
0
 /**
  * {@inheritdoc}
  */
 protected function send(string $data, float $timeout = 0, bool $end = false) : \Generator
 {
     if (false === ($data = deflate_add($this->resource, $data, $end ? \ZLIB_FINISH : \ZLIB_SYNC_FLUSH))) {
         throw new FailureException('Failed adding date to deflate stream.');
     }
     return yield from parent::send($data, $timeout, $end);
 }
示例#2
0
 /**
  * {@inheritdoc}
  *
  * @throws \Icicle\Http\Exception\MessageException If an invalid chunk length is found.
  */
 protected function send(string $data, float $timeout = 0, bool $end = false) : \Generator
 {
     $this->buffer->push($data);
     $data = '';
     while (!$this->buffer->isEmpty()) {
         if (0 === $this->length) {
             // Read chunk length.
             if (false === ($position = $this->buffer->search("\r\n"))) {
                 return yield from parent::send($data, $timeout, $end);
             }
             $length = rtrim($this->buffer->remove($position + 2), "\r\n");
             if ($position = strpos($length, ';')) {
                 $length = substr($length, 0, $position);
             }
             if (!preg_match('/^[a-f0-9]+$/i', $length)) {
                 yield from parent::send('', $timeout, true);
                 throw new MessageException(Response::BAD_REQUEST, 'Invalid chunk length.');
             }
             $this->length = hexdec($length) + 2;
             if (2 === $this->length) {
                 // Termination chunk.
                 $end = true;
             }
         }
         if (2 < $this->length) {
             // Read chunk.
             $buffer = $this->buffer->remove($this->length - 2);
             $this->length -= strlen($buffer);
             $data .= $buffer;
         }
         if (2 >= $this->length) {
             // Remove \r\n after chunk.
             $this->length -= strlen($this->buffer->remove($this->length));
         }
     }
     return yield from parent::send($data, $timeout, $end);
 }
示例#3
0
 /**
  * @coroutine
  *
  * @param \Icicle\Http\Message\Message $message
  * @param float|int $timeout
  *
  * @return \Generator
  *
  * @resolve \Icicle\Http\Message\Message
  *
  * @throws \Icicle\Http\Exception\MessageException
  */
 private function buildIncomingStream(Message $message, float $timeout = 0) : \Generator
 {
     $body = $message->getBody();
     if ($body instanceof SeekableStream && $body->isOpen()) {
         yield from $body->seek(0);
     }
     if (!$body->isReadable()) {
         return $message;
     }
     if (strtolower($message->getHeader('Transfer-Encoding') === 'chunked')) {
         $stream = new ChunkedDecoder($this->hwm);
         $coroutine = new Coroutine(Stream\pipe($body, $stream, true, 0, null, $timeout));
         $coroutine->done(null, [$stream, 'close']);
         $message = $message->withBody($stream);
     } elseif ($message->hasHeader('Content-Length')) {
         $length = (int) $message->getHeader('Content-Length');
         if (0 > $length) {
             throw new MessageException(Response::BAD_REQUEST, 'Content-Length header invalid.');
         }
         $stream = new MemoryStream($this->hwm);
         if (0 === $length) {
             yield from $stream->end();
         } else {
             $coroutine = new Coroutine(Stream\pipe($body, $stream, true, $length, null, $timeout));
             $coroutine->done(null, [$stream, 'close']);
         }
         $message = $message->withBody($stream);
     } elseif ($message instanceof Request) {
         switch ($message->getMethod()) {
             case 'POST':
             case 'PUT':
                 // Post and put messages must have content length or be transfer encoded.
                 throw new MessageException(Response::LENGTH_REQUIRED, 'Content-Length header required.');
             default:
                 // Assume 0 length body.
                 $stream = new MemoryStream();
                 yield from $stream->end();
                 // Creates empty request body.
                 return $message->withBody($stream);
         }
     } elseif (strtolower($message->getHeader('Connection')) !== 'close') {
         throw new MessageException(Response::LENGTH_REQUIRED, 'Content-Length header required.');
     }
     $contentEncoding = strtolower($message->getHeader('Content-Encoding'));
     switch ($contentEncoding) {
         case 'deflate':
             $stream = new ZlibDecoder(ZlibDecoder::DEFLATE, $this->hwm);
             break;
         case 'gzip':
             $stream = new ZlibDecoder(ZlibDecoder::GZIP, $this->hwm);
             break;
         case '':
             // No content encoding.
             return $message;
         default:
             throw new MessageException(Response::BAD_REQUEST, sprintf('Unsupported content encoding received: %s', $contentEncoding));
     }
     $coroutine = new Coroutine(Stream\pipe($message->getBody(), $stream, true, 0, null, $timeout));
     $coroutine->done(null, [$stream, 'close']);
     return $message->withBody($stream);
 }