bool SimpleHttpClient::readHeader () {
      char* pos = (char*) memchr(_readBuffer.c_str(), '\n', _readBuffer.length());

      while (pos) {
        // size_t is unsigned, should never get < 0
        assert(pos >= _readBuffer.c_str());

        size_t len = pos - _readBuffer.c_str();
        string line(_readBuffer.c_str(), len);
        _readBuffer.erase_front(len + 1);

        //printf("found header line %s\n", line.c_str());

        if (line == "\r" || line == "") {
          // end of header found
          if (_result->isChunked()) {
            _state = IN_READ_CHUNKED_HEADER;
            return readChunkedHeader();
          }
          else if (! _result->hasContentLength()) {
            // no content-length header in response
            _state = IN_READ_BODY;
            return readBody();
          }
          else if (_result->hasContentLength() && _result->getContentLength() > 0) {
            // found content-length header in response
            if (_result->getContentLength() > _maxPacketSize) {
              setErrorMessage("Content-Length > max packet size found", true);

              // reset connection
              this->close();
              _state = DEAD;

              return false;
            }

            _state = IN_READ_BODY;
            return readBody();
          }
          else {
            _result->setResultType(SimpleHttpResult::COMPLETE);
            _state = FINISHED;

            if (! _keepAlive) {
              _connection->disconnect();
            }
          }
          break;
        }
        else {
          _result->addHeaderField(line);
        }

        pos = (char*) memchr(_readBuffer.c_str(), '\n', _readBuffer.length());
      }
      return true;
    }
Esempio n. 2
0
    bool SimpleHttpClient::readChunkedBody () {

      if (_readBuffer.length() >= _nextChunkedSize) {

        _result->getBody().write(_readBuffer.c_str(), (size_t) _nextChunkedSize);
        _readBuffer.erase_front((size_t) _nextChunkedSize);
        _state = IN_READ_CHUNKED_HEADER;
        return readChunkedHeader();
      }

      return true;
    }
Esempio n. 3
0
    bool SimpleHttpClient::readHeader () {
      char* pos = (char*) memchr(_readBuffer.c_str(), '\n', _readBuffer.length());

      while (pos) {
        size_t len = pos - _readBuffer.c_str();
        string line(_readBuffer.c_str(), len);
        _readBuffer.erase_front(len + 1);

        //printf("found header line %s\n", line.c_str());

        if (line == "\r" || line == "") {
          // end of header found
          if (_result->isChunked()) {
            _state = IN_READ_CHUNKED_HEADER;
            return readChunkedHeader();
          }
          else if (_result->getContentLength()) {
            
            if (_result->getContentLength() > 5000000) {
              _errorMessage = "Content length > 5000000 bytes found!";
              LOGGER_ERROR << "Content length > 5000000 bytes found! Closing connection.";
              
              // reset connection 
              close();
          
              return false;              
            }

            _state = IN_READ_BODY;
            return readBody();
          }
          else {
            _result->setResultType(SimpleHttpResult::COMPLETE);
            _state = FINISHED;
          }
          break;
        }
        else {
          _result->addHeaderField(line);
        }

        pos = (char*) memchr(_readBuffer.c_str(), '\n', _readBuffer.length());
      }
      return true;
    }
Esempio n. 4
0
    bool SimpleHttpClient::read () {
      if (!checkSocket()) {
        return false;
      }

     do {
        char buffer[READBUFFER_SIZE];

        int len_read = ::read(_socket, buffer, READBUFFER_SIZE - 1);

        if (len_read <= 0) {
          // error: stop reading
          break;
        }

        _readBuffer.appendText(buffer, len_read);
      }
      while(readable());

      switch (_state) {
        case (IN_READ_HEADER):
          readHeader();
          break;

        case (IN_READ_BODY):
          readBody();
          break;

        case (IN_READ_CHUNKED_HEADER):
          readChunkedHeader();
          break;

        case (IN_READ_CHUNKED_BODY):
          readChunkedBody();
          break;

        default:
          break;
      }
      return true;
    }
    bool SimpleHttpClient::readChunkedBody () {
      if (_method == HttpRequest::HTTP_REQUEST_HEAD) {
        // HEAD requests may be responded to without a body...
        _result->setResultType(SimpleHttpResult::COMPLETE);
        _state = FINISHED;
        if (! _keepAlive) {
          _connection->disconnect();
        }
        return true;
      }

      if (_readBuffer.length() >= _nextChunkedSize) {

        _result->getBody().write(_readBuffer.c_str(), (size_t) _nextChunkedSize);
        _readBuffer.erase_front((size_t) _nextChunkedSize);
        _state = IN_READ_CHUNKED_HEADER;
        return readChunkedHeader();
      }

      return true;
    }
Esempio n. 6
0
    SimpleHttpResult* SimpleHttpClient::request (rest::HttpRequest::HttpRequestType method,
            const string& location,
            const char* body,
            size_t bodyLength,
            const map<string, string>& headerFields) {
     
      assert(_result == 0);
       
      _result = new SimpleHttpResult;
      _errorMessage = "";

      // set body to all connections
      setRequest(method, location, body, bodyLength, headerFields);

      double endTime = now() + _requestTimeout;
      double remainingTime = _requestTimeout;

      while (isWorking() && remainingTime > 0.0) {
        switch (_state) {
          case (IN_CONNECT): {
            handleConnect();
            break;
          }

          case (IN_WRITE): {
            size_t bytesWritten = 0;

            TRI_set_errno(TRI_ERROR_NO_ERROR);
            if (! _connection->handleWrite(remainingTime, (void*) (_writeBuffer.c_str() + _written), _writeBuffer.length() - _written, &bytesWritten)) {
              setErrorMessage(TRI_last_error(), false);
              this->close();
            }
            else {
              _written += bytesWritten;
              if (_written == _writeBuffer.length())  {
                _state = IN_READ_HEADER;        
              }
            }
            break;
          }

          case (IN_READ_HEADER):
          case (IN_READ_BODY):
          case (IN_READ_CHUNKED_HEADER):
          case (IN_READ_CHUNKED_BODY): {
            TRI_set_errno(TRI_ERROR_NO_ERROR);
            if (_connection->handleRead(remainingTime, _readBuffer)) {
              switch (_state) {
                case (IN_READ_HEADER):
                  readHeader();
                  break;
                case (IN_READ_BODY):
                  readBody();
                  break;
                case (IN_READ_CHUNKED_HEADER):
                  readChunkedHeader();
                  break;
                case (IN_READ_CHUNKED_BODY):
                  readChunkedBody();
                  break;
                default:
                  break;
              }
            }
            else {
              setErrorMessage(TRI_last_error(), false);
              this->close();
            }
            break;
          }
          default:
            break;
        }

        remainingTime = endTime - now();
      }
      
      if (isWorking() && _errorMessage == "" ) {
        setErrorMessage("Request timeout reached");
      }
      
      // set result type in getResult()
      SimpleHttpResult* result = getResult();
      
      _result = 0;
      
      return result;
    }