示例#1
0
  Variant execute() {
    ASSERT(!m_exception);
    if (m_cp == NULL) {
      return false;
    }
    if (m_emptyPost) {
      // As per curl docs, an empty post must set POSTFIELDSIZE to be 0 or
      // the reader function will be called
      curl_easy_setopt(m_cp, CURLOPT_POSTFIELDSIZE, 0);
    }
    m_write.buf.reset();
    m_write.content.clear();
    m_header.clear();
    memset(m_error_str, 0, sizeof(m_error_str));

    {
      IOStatusHelper io("curl_easy_perform", m_url.data());
      SYNC_VM_REGS_SCOPED();
      m_error_no = curl_easy_perform(m_cp);
      if (m_exception) {
        if (m_phpException) {
          Object e((ObjectData*)m_exception);
          m_exception = NULL;
          e.get()->decRefCount();
          throw e;
        } else {
          Exception *e = (Exception*)m_exception;
          m_exception = NULL;
          e->throwException();
        }
      }
    }
    set_curl_statuses(m_cp, m_url.data());

    /* CURLE_PARTIAL_FILE is returned by HEAD requests */
    if (m_error_no != CURLE_OK && m_error_no != CURLE_PARTIAL_FILE) {
      m_write.buf.reset();
      m_write.content.clear();
      return false;
    }

    if (m_write.method == PHP_CURL_RETURN) {
      if (!m_write.buf.empty()) {
        m_write.content = m_write.buf.detach();
      }
      if (!m_write.content.empty()) {
        return m_write.content;
      }
    }
    if (m_write.method == PHP_CURL_RETURN) {
      return String("");
    }
    return true;
  }
示例#2
0
int HttpClient::request(const char* verb,
                     const char *url, const char *data, size_t size,
                     StringBuffer &response, const HeaderMap *requestHeaders,
                     req::vector<String> *responseHeaders) {
  SlowTimer timer(RuntimeOption::HttpSlowQueryThreshold, "curl", url);

  m_response = &response;

  char error_str[CURL_ERROR_SIZE + 1];
  memset(error_str, 0, sizeof(error_str));

  CURL *cp = curl_easy_init();
  curl_easy_setopt(cp, CURLOPT_URL,               url);
  curl_easy_setopt(cp, CURLOPT_WRITEFUNCTION,     curl_write);
  curl_easy_setopt(cp, CURLOPT_WRITEDATA,         (void*)this);
  curl_easy_setopt(cp, CURLOPT_ERRORBUFFER,       error_str);
  curl_easy_setopt(cp, CURLOPT_NOPROGRESS,        1);
  curl_easy_setopt(cp, CURLOPT_VERBOSE,           0);
  curl_easy_setopt(cp, CURLOPT_NOSIGNAL,          1);
  curl_easy_setopt(cp, CURLOPT_DNS_USE_GLOBAL_CACHE, 0); // for thread-safe
  curl_easy_setopt(cp, CURLOPT_DNS_CACHE_TIMEOUT, 120);
  curl_easy_setopt(cp, CURLOPT_NOSIGNAL, 1); // for multithreading mode
  curl_easy_setopt(cp, CURLOPT_SSL_VERIFYPEER,    1);
  // For libcurl the VERIFYHOST "true"/enabled value is '2', NOT '1'!
  // If libcurl is built with NSS, VERIFYPEER =0 forces VERIFYHOST to =0
  curl_easy_setopt(cp, CURLOPT_SSL_VERIFYHOST,    2);
  curl_easy_setopt(cp, CURLOPT_SSL_CTX_FUNCTION, curl_tls_workarounds_cb);
  curl_easy_setopt(cp, CURLOPT_USE_SSL, m_use_ssl);
  curl_easy_setopt(cp, CURLOPT_SSLVERSION, m_sslversion);

  /*
   * cipher list varies according to SSL library, and "ALL" is for OpenSSL
   */
  curl_version_info_data *cver = curl_version_info(CURLVERSION_NOW);
  if (cver && cver->ssl_version && strstr(cver->ssl_version, "OpenSSL")) {
    curl_easy_setopt(cp, CURLOPT_SSL_CIPHER_LIST, "ALL");
  }

  curl_easy_setopt(cp, CURLOPT_TIMEOUT,           m_timeout);
  if (m_maxRedirect > 1) {
    curl_easy_setopt(cp, CURLOPT_FOLLOWLOCATION,    1);
    curl_easy_setopt(cp, CURLOPT_MAXREDIRS,         m_maxRedirect);
  } else {
    curl_easy_setopt(cp, CURLOPT_FOLLOWLOCATION,    0);
  }
  if (!m_use11) {
    curl_easy_setopt(cp, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
  }
  if (m_decompress) {
    curl_easy_setopt(cp, CURLOPT_ENCODING, "");
  }

  if (!m_username.empty()) {
    curl_easy_setopt(cp, CURLOPT_HTTPAUTH,
                     m_basic ? CURLAUTH_BASIC : CURLAUTH_DIGEST);
    curl_easy_setopt(cp, CURLOPT_USERNAME, m_username.c_str());
    curl_easy_setopt(cp, CURLOPT_PASSWORD, m_password.c_str());
  }

  if (!m_proxyHost.empty() && m_proxyPort) {
    curl_easy_setopt(cp, CURLOPT_PROXY,     m_proxyHost.c_str());
    curl_easy_setopt(cp, CURLOPT_PROXYPORT, m_proxyPort);
    if (!m_proxyUsername.empty()) {
      curl_easy_setopt(cp, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
      curl_easy_setopt(cp, CURLOPT_PROXYUSERNAME, m_proxyUsername.c_str());
      curl_easy_setopt(cp, CURLOPT_PROXYPASSWORD, m_proxyPassword.c_str());
    }
  }

  curl_slist *slist = nullptr;
  if (requestHeaders) {
    for (HeaderMap::const_iterator iter = requestHeaders->begin();
         iter != requestHeaders->end(); ++iter) {
      for (unsigned int i = 0; i < iter->second.size(); i++) {
        String header = iter->first + ": " + iter->second[i];
        slist = curl_slist_append(slist, header.data());
      }
    }
  if (m_stream_context_options[s_http].isArray()) {
    const Array http = m_stream_context_options[s_http].toArray();
    if (http.exists(s_header)) {
      slist = curl_slist_append(slist,
                                http[s_header].toString().data());
    }
  }
  if (slist) {
      curl_easy_setopt(cp, CURLOPT_HTTPHEADER, slist);
    }
  }

  if (data && size) {
    curl_easy_setopt(cp, CURLOPT_POST,          1);
    curl_easy_setopt(cp, CURLOPT_POSTFIELDS,    data);
    if (size <= 0x7fffffffLL) {
      curl_easy_setopt(cp, CURLOPT_POSTFIELDSIZE, size);
    } else {
      curl_easy_setopt(cp, CURLOPT_POSTFIELDSIZE_LARGE, size);
    }
  }

  if (verb != nullptr) {
    curl_easy_setopt(cp, CURLOPT_CUSTOMREQUEST, verb);

    if (strcasecmp(verb, "HEAD") == 0) {
      curl_easy_setopt(cp, CURLOPT_NOBODY, 1);
    }
  }

  if (responseHeaders) {
    m_responseHeaders = responseHeaders;
    curl_easy_setopt(cp, CURLOPT_HEADERFUNCTION, curl_header);
    curl_easy_setopt(cp, CURLOPT_WRITEHEADER, (void*)this);
  }

  if (m_stream_context_options[s_ssl].isArray() ||
      m_stream_context_options[s_tls].isArray()) {
    const Array ssl = m_stream_context_options[s_ssl].isArray() ? \
                      m_stream_context_options[s_ssl].toArray() : \
                      m_stream_context_options[s_tls].toArray();
    if (ssl.exists(s_verify_peer)) {
      curl_easy_setopt(cp, CURLOPT_SSL_VERIFYPEER,
                       ssl[s_verify_peer].toBoolean());
    }
    if (ssl.exists(s_verify_peer_name)) {
      // For libcurl VERIFYHOST the enable/"true" value is '2', NOT '1'!
      curl_easy_setopt(cp, CURLOPT_SSL_VERIFYHOST,
                       ssl[s_verify_peer_name].toBoolean() ? \
                       2 : 0);
    }
    if (ssl.exists(s_capath)) {
      curl_easy_setopt(cp, CURLOPT_CAPATH,
                       ssl[s_capath].toString().data());
    }
    if (ssl.exists(s_cafile)) {
      curl_easy_setopt(cp, CURLOPT_CAINFO,
                       ssl[s_cafile].toString().data());
    }
    if (ssl.exists(s_local_cert)) {
      curl_easy_setopt(cp, CURLOPT_SSLKEY,
                       ssl[s_local_cert].toString().data());
      curl_easy_setopt(cp, CURLOPT_SSLKEYTYPE, "PEM");
    }
    if (ssl.exists(s_passphrase)) {
      curl_easy_setopt(cp, CURLOPT_KEYPASSWD,
                       ssl[s_passphrase].toString().data());
    }
  }

  long code = 0;
  {
    IOStatusHelper io("http", url);
    CURLcode error_no = curl_easy_perform(cp);
    if (error_no != CURLE_OK) {
      m_error = error_str;
    } else {
      curl_easy_getinfo(cp, CURLINFO_RESPONSE_CODE, &code);
    }
  }

  set_curl_statuses(cp, url);

  if (slist) {
    curl_slist_free_all(slist);
  }

  curl_easy_cleanup(cp);
  return code;
}
int HttpClient::impl(const char *url, const char *data, int size,
                     StringBuffer &response, const HeaderMap *requestHeaders,
                     std::vector<String> *responseHeaders) {
  SlowTimer timer(RuntimeOption::HttpSlowQueryThreshold, "curl", url);

  m_response = &response;

  char error_str[CURL_ERROR_SIZE + 1];
  memset(error_str, 0, sizeof(error_str));

  CURL *cp = curl_easy_init();
  curl_easy_setopt(cp, CURLOPT_URL,               url);
  curl_easy_setopt(cp, CURLOPT_WRITEFUNCTION,     curl_write);
  curl_easy_setopt(cp, CURLOPT_WRITEDATA,         (void*)this);
  curl_easy_setopt(cp, CURLOPT_ERRORBUFFER,       error_str);
  curl_easy_setopt(cp, CURLOPT_NOPROGRESS,        1);
  curl_easy_setopt(cp, CURLOPT_VERBOSE,           0);
  curl_easy_setopt(cp, CURLOPT_NOSIGNAL,          1);
  curl_easy_setopt(cp, CURLOPT_DNS_USE_GLOBAL_CACHE, 0); // for thread-safe
  curl_easy_setopt(cp, CURLOPT_DNS_CACHE_TIMEOUT, 120);
  curl_easy_setopt(cp, CURLOPT_NOSIGNAL, 1); // for multithreading mode
  curl_easy_setopt(cp, CURLOPT_SSL_VERIFYPEER,    0);
  curl_easy_setopt(cp, CURLOPT_SSL_CTX_FUNCTION, curl_tls_workarounds_cb);

  curl_easy_setopt(cp, CURLOPT_TIMEOUT,           m_timeout);
  if (m_maxRedirect > 1) {
    curl_easy_setopt(cp, CURLOPT_FOLLOWLOCATION,    1);
    curl_easy_setopt(cp, CURLOPT_MAXREDIRS,         m_maxRedirect);
  } else {
    curl_easy_setopt(cp, CURLOPT_FOLLOWLOCATION,    0);
  }
  if (!m_use11) {
    curl_easy_setopt(cp, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
  }
  if (m_decompress) {
    curl_easy_setopt(cp, CURLOPT_ENCODING, "");
  }

  if (!m_username.empty()) {
    curl_easy_setopt(cp, CURLOPT_HTTPAUTH,
                     m_basic ? CURLAUTH_BASIC : CURLAUTH_DIGEST);
    curl_easy_setopt(cp, CURLOPT_USERNAME, m_username.c_str());
    curl_easy_setopt(cp, CURLOPT_PASSWORD, m_password.c_str());
  }

  if (!m_proxyHost.empty() && m_proxyPort) {
    curl_easy_setopt(cp, CURLOPT_PROXY,     m_proxyHost.c_str());
    curl_easy_setopt(cp, CURLOPT_PROXYPORT, m_proxyPort);
    if (!m_proxyUsername.empty()) {
      curl_easy_setopt(cp, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
      curl_easy_setopt(cp, CURLOPT_PROXYUSERNAME, m_proxyUsername.c_str());
      curl_easy_setopt(cp, CURLOPT_PROXYPASSWORD, m_proxyPassword.c_str());
    }
  }

  std::vector<String> headers; // holding those temporary strings
  curl_slist *slist = nullptr;
  if (requestHeaders) {
    for (HeaderMap::const_iterator iter = requestHeaders->begin();
         iter != requestHeaders->end(); ++iter) {
      for (unsigned int i = 0; i < iter->second.size(); i++) {
        String header = iter->first + ": " + iter->second[i];
        headers.push_back(header);
        slist = curl_slist_append(slist, header.data());
      }
    }
    if (slist) {
      curl_easy_setopt(cp, CURLOPT_HTTPHEADER, slist);
    }
  }

  if (data && size) {
    curl_easy_setopt(cp, CURLOPT_POST,          1);
    curl_easy_setopt(cp, CURLOPT_POSTFIELDS,    data);
    curl_easy_setopt(cp, CURLOPT_POSTFIELDSIZE, size);
  }

  if (responseHeaders) {
    m_responseHeaders = responseHeaders;
    curl_easy_setopt(cp, CURLOPT_HEADERFUNCTION, curl_header);
    curl_easy_setopt(cp, CURLOPT_WRITEHEADER, (void*)this);
  }

  if (m_stream_context_options[s_ssl].isArray()) {
    const Array ssl = m_stream_context_options[s_ssl].toArray();
    if (ssl[s_verify_peer].toBoolean()) {
      curl_easy_setopt(cp, CURLOPT_SSL_VERIFYPEER, 1);
    }
    if (ssl.exists(s_capath)) {
      curl_easy_setopt(cp, CURLOPT_CAPATH,
                       ssl[s_capath].toString().data());
    }
    if (ssl.exists(s_cafile)) {
      curl_easy_setopt(cp, CURLOPT_CAINFO,
                       ssl[s_cafile].toString().data());
    }
    if (ssl.exists(s_local_cert)) {
      curl_easy_setopt(cp, CURLOPT_SSLKEY,
                       ssl[s_local_cert].toString().data());
      curl_easy_setopt(cp, CURLOPT_SSLKEYTYPE, "PEM");
    }
    if (ssl.exists(s_passphrase)) {
      curl_easy_setopt(cp, CURLOPT_KEYPASSWD,
                       ssl[s_passphrase].toString().data());
    }
  }

  long code = 0;
  {
    IOStatusHelper io("http", url);
    CURLcode error_no = curl_easy_perform(cp);
    if (error_no != CURLE_OK) {
      m_error = error_str;
    } else {
      curl_easy_getinfo(cp, CURLINFO_RESPONSE_CODE, &code);
    }
  }

  set_curl_statuses(cp, url);

  if (slist) {
    curl_slist_free_all(slist);
  }

  curl_easy_cleanup(cp);
  return code;
}