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; }
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; }