示例#1
0
 /**
  * Reads a part of response body encoded with chunked Transfer-Encoding
  *
  * @param int $bufferSize buffer size to use for reading
  *
  * @return   string
  * @throws   HTTP_Request2_MessageException
  */
 protected function readChunked($bufferSize)
 {
     // at start of the next chunk?
     if (0 == $this->chunkLength) {
         $line = $this->socket->readLine($bufferSize);
         if ('' === $line && $this->socket->eof()) {
             $this->chunkLength = -1;
             // indicate missing chunk
             return '';
         } elseif (!preg_match('/^([0-9a-f]+)/i', $line, $matches)) {
             throw new HTTP_Request2_MessageException("Cannot decode chunked response, invalid chunk length '{$line}'", HTTP_Request2_Exception::DECODE_ERROR);
         } else {
             $this->chunkLength = hexdec($matches[1]);
             // Chunk with zero length indicates the end
             if (0 == $this->chunkLength) {
                 $this->socket->readLine($bufferSize);
                 return '';
             }
         }
     }
     $data = $this->socket->read(min($this->chunkLength, $bufferSize));
     $this->chunkLength -= strlen($data);
     if (0 == $this->chunkLength) {
         $this->socket->readLine($bufferSize);
         // Trailing CRLF
     }
     return $data;
 }
示例#2
0
 /**
  * Reads the remote server's response
  *
  * @return   HTTP_Request2_Response
  * @throws   HTTP_Request2_Exception
  */
 protected function readResponse()
 {
     $bufferSize = $this->request->getConfig('buffer_size');
     do {
         $response = new HTTP_Request2_Response($this->socket->readLine($bufferSize), true, $this->request->getUrl());
         do {
             $headerLine = $this->socket->readLine($bufferSize);
             $response->parseHeaderLine($headerLine);
         } while ('' != $headerLine);
     } while (in_array($response->getStatus(), array(100, 101)));
     $this->request->setLastEvent('receivedHeaders', $response);
     // No body possible in such responses
     if (HTTP_Request2::METHOD_HEAD == $this->request->getMethod() || HTTP_Request2::METHOD_CONNECT == $this->request->getMethod() && 200 <= $response->getStatus() && 300 > $response->getStatus() || in_array($response->getStatus(), array(204, 304))) {
         return $response;
     }
     $chunked = 'chunked' == $response->getHeader('transfer-encoding');
     $length = $response->getHeader('content-length');
     $hasBody = false;
     if ($chunked || null === $length || 0 < intval($length)) {
         // RFC 2616, section 4.4:
         // 3. ... If a message is received with both a
         // Transfer-Encoding header field and a Content-Length header field,
         // the latter MUST be ignored.
         $toRead = $chunked || null === $length ? null : $length;
         $this->chunkLength = 0;
         while (!$this->socket->eof() && (is_null($toRead) || 0 < $toRead)) {
             if ($chunked) {
                 $data = $this->readChunked($bufferSize);
             } elseif (is_null($toRead)) {
                 $data = $this->socket->read($bufferSize);
             } else {
                 $data = $this->socket->read(min($toRead, $bufferSize));
                 $toRead -= strlen($data);
             }
             if ('' == $data && (!$this->chunkLength || $this->socket->eof())) {
                 break;
             }
             $hasBody = true;
             if ($this->request->getConfig('store_body')) {
                 $response->appendBody($data);
             }
             if (!in_array($response->getHeader('content-encoding'), array('identity', null))) {
                 $this->request->setLastEvent('receivedEncodedBodyPart', $data);
             } else {
                 $this->request->setLastEvent('receivedBodyPart', $data);
             }
         }
     }
     if ($hasBody) {
         $this->request->setLastEvent('receivedBody', $response);
     }
     return $response;
 }
示例#3
0
 /**
  * Reads the remote server's response
  *
  * @return   HTTP_Request2_Response
  * @throws   HTTP_Request2_Exception
  */
 protected function readResponse()
 {
     $bufferSize = $this->request->getConfig('buffer_size');
     // http://tools.ietf.org/html/rfc2616#section-8.2.3
     // ...the client SHOULD NOT wait for an indefinite period before sending the request body
     $timeout = $this->expect100Continue ? 1 : null;
     do {
         try {
             $response = new HTTP_Request2_Response($this->socket->readLine($bufferSize, $timeout), true, $this->request->getUrl());
             do {
                 $headerLine = $this->socket->readLine($bufferSize);
                 $response->parseHeaderLine($headerLine);
             } while ('' != $headerLine);
         } catch (HTTP_Request2_MessageException $e) {
             if (HTTP_Request2_Exception::TIMEOUT === $e->getCode() && $this->expect100Continue) {
                 return null;
             }
             throw $e;
         }
         if ($this->expect100Continue && 100 == $response->getStatus()) {
             return $response;
         }
     } while (in_array($response->getStatus(), array(100, 101)));
     $this->request->setLastEvent('receivedHeaders', $response);
     // No body possible in such responses
     if (HTTP_Request2::METHOD_HEAD == $this->request->getMethod() || HTTP_Request2::METHOD_CONNECT == $this->request->getMethod() && 200 <= $response->getStatus() && 300 > $response->getStatus() || in_array($response->getStatus(), array(204, 304))) {
         return $response;
     }
     $chunked = 'chunked' == $response->getHeader('transfer-encoding');
     $length = $response->getHeader('content-length');
     $hasBody = false;
     if ($chunked || null === $length || 0 < intval($length)) {
         // RFC 2616, section 4.4:
         // 3. ... If a message is received with both a
         // Transfer-Encoding header field and a Content-Length header field,
         // the latter MUST be ignored.
         $toRead = $chunked || null === $length ? null : $length;
         $this->chunkLength = 0;
         while (!$this->socket->eof() && (is_null($toRead) || 0 < $toRead)) {
             if ($chunked) {
                 $data = $this->readChunked($bufferSize);
             } elseif (is_null($toRead)) {
                 $data = $this->socket->read($bufferSize);
             } else {
                 $data = $this->socket->read(min($toRead, $bufferSize));
                 $toRead -= strlen($data);
             }
             if ('' == $data && (!$this->chunkLength || $this->socket->eof())) {
                 break;
             }
             $hasBody = true;
             if ($this->request->getConfig('store_body')) {
                 $response->appendBody($data);
             }
             if (!in_array($response->getHeader('content-encoding'), array('identity', null))) {
                 $this->request->setLastEvent('receivedEncodedBodyPart', $data);
             } else {
                 $this->request->setLastEvent('receivedBodyPart', $data);
             }
         }
     }
     if ($hasBody) {
         $this->request->setLastEvent('receivedBody', $response);
     }
     return $response;
 }