Files
Http/Http/HttpClientImpl.cpp
T
2020-03-27 15:44:23 +01:00

801 lines
26 KiB
C++

#include "HttpClientImpl.h"
#include "HttpClientHelpers.h"
#include <Logging.h>
#include <StringAlgorithm.h>
#include <curl/curl.h>
#include <openssl/crypto.h>
#include <fstream>
#include <sstream>
namespace Http {
HttpClientImpl::HttpClientImpl(int timeout) :
m_timeout(timeout)
{
curl_global_init(CURL_GLOBAL_ALL);
m_userAgents.push_back("Opera/9.80 (X11; Linux i686; U; en) Presto/2.7.62 Version/11.00");
InitializeLocks();
}
HttpClientImpl::~HttpClientImpl()
{
FreeLocks();
curl_global_cleanup();
}
int HttpClientImpl::GetUrlReturnCode(const std::string& url) const
{
return std::stoi(PerformOperation(HttpClientImpl::Operation::Silent, HttpClientImpl::Method::GET, url, std::vector<std::string>(), std::string(), std::string(), true));
}
std::string HttpClientImpl::GetUrlContents(const std::string& url) const
{
return PerformOperation(HttpClientImpl::Operation::GetContent, HttpClientImpl::Method::GET, url);
}
void HttpClientImpl::GetUrlSilent(const std::string& url) const
{
PerformOperation(HttpClientImpl::Operation::Silent, HttpClientImpl::Method::GET, url);
}
std::string HttpClientImpl::GetUrlRedirect(const std::string& url) const
{
return PerformOperation(HttpClientImpl::Operation::GetRedirect, HttpClientImpl::Method::GET, url);
}
std::string HttpClientImpl::GetUrlContents(const std::string& url, const std::vector<std::string>& httpHeaders) const
{
return PerformOperation(HttpClientImpl::Operation::GetContent, HttpClientImpl::Method::GET, url, httpHeaders);
}
void HttpClientImpl::GetUrlSilent(const std::string& url, const std::vector<std::string>& httpHeaders) const
{
PerformOperation(HttpClientImpl::Operation::Silent, HttpClientImpl::Method::GET, url, httpHeaders);
}
std::string HttpClientImpl::GetUrlRedirect(const std::string& url, const std::vector<std::string>& httpHeaders) const
{
return PerformOperation(HttpClientImpl::Operation::GetRedirect, HttpClientImpl::Method::GET, url, httpHeaders);
}
std::string HttpClientImpl::GetUrlContents(const std::string& url, const std::string& cookieFile) const
{
return PerformOperation(HttpClientImpl::Operation::GetContent, HttpClientImpl::Method::GET, url, std::vector<std::string>(), cookieFile);
}
void HttpClientImpl::GetUrlSilent(const std::string& url, const std::string& cookieFile) const
{
PerformOperation(HttpClientImpl::Operation::Silent, HttpClientImpl::Method::GET, url, std::vector<std::string>(), cookieFile);
}
std::string HttpClientImpl::GetUrlRedirect(const std::string& url, const std::string& cookieFile) const
{
return PerformOperation(HttpClientImpl::Operation::GetRedirect, HttpClientImpl::Method::GET, url, std::vector<std::string>(), cookieFile);
}
std::string HttpClientImpl::GetUrlContents(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& cookieFile) const
{
return PerformOperation(HttpClientImpl::Operation::GetContent, HttpClientImpl::Method::GET, url, httpHeaders, cookieFile);
}
void HttpClientImpl::GetUrlSilent(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& cookieFile) const
{
PerformOperation(HttpClientImpl::Operation::Silent, HttpClientImpl::Method::GET, url, httpHeaders, cookieFile);
}
std::string HttpClientImpl::GetUrlRedirect(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& cookieFile) const
{
return PerformOperation(HttpClientImpl::Operation::GetRedirect, HttpClientImpl::Method::GET, url, httpHeaders, cookieFile);
}
std::string HttpClientImpl::PutUrlContents(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& data) const
{
return PerformOperation(HttpClientImpl::Operation::GetContent, HttpClientImpl::Method::PUT, url, httpHeaders, std::string(), data);
}
void HttpClientImpl::PutUrlSilent(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& data) const
{
PerformOperation(HttpClientImpl::Operation::Silent, HttpClientImpl::Method::PUT, url, httpHeaders, std::string(), data);
}
std::string HttpClientImpl::PutUrlRedirect(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& data) const
{
return PerformOperation(HttpClientImpl::Operation::GetRedirect, HttpClientImpl::Method::PUT, url, httpHeaders, std::string(), data);
}
std::string HttpClientImpl::PutUrlContents(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& cookieFile, const std::string& data) const
{
return PerformOperation(HttpClientImpl::Operation::GetContent, HttpClientImpl::Method::PUT, url, httpHeaders, cookieFile, data);
}
void HttpClientImpl::PutUrlSilent(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& cookieFile, const std::string& data) const
{
PerformOperation(HttpClientImpl::Operation::Silent, HttpClientImpl::Method::PUT, url, httpHeaders, cookieFile, data);
}
std::string HttpClientImpl::PutUrlRedirect(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& cookieFile, const std::string& data) const
{
return PerformOperation(HttpClientImpl::Operation::GetRedirect, HttpClientImpl::Method::PUT, url, httpHeaders, cookieFile, data);
}
std::string HttpClientImpl::GetUrlPostContents(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& data) const
{
return PerformOperation(HttpClientImpl::Operation::GetContent, HttpClientImpl::Method::POST, url, httpHeaders, std::string(), data);
}
void HttpClientImpl::GetUrlPostSilent(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& data) const
{
PerformOperation(HttpClientImpl::Operation::Silent, HttpClientImpl::Method::POST, url, httpHeaders, std::string(), data);
}
std::string HttpClientImpl::GetUrlPostRedirect(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& data) const
{
return PerformOperation(HttpClientImpl::Operation::GetRedirect, HttpClientImpl::Method::POST, url, httpHeaders, std::string(), data);
}
std::string HttpClientImpl::GetUrlPostContents(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& cookieFile, const std::string& data) const
{
return PerformOperation(HttpClientImpl::Operation::GetContent, HttpClientImpl::Method::POST, url, httpHeaders, cookieFile, data);
}
void HttpClientImpl::GetUrlPostSilent(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& cookieFile, const std::string& data) const
{
PerformOperation(HttpClientImpl::Operation::Silent, HttpClientImpl::Method::POST, url, httpHeaders, cookieFile, data);
}
std::string HttpClientImpl::GetUrlPostRedirect(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& cookieFile, const std::string& data) const
{
return PerformOperation(HttpClientImpl::Operation::GetRedirect, HttpClientImpl::Method::POST, url, httpHeaders, cookieFile, data);
}
std::string HttpClientImpl::GetUrlPostAttachmentContents(const std::string& url, const std::string& data, const std::string& filename, const std::string& fileFieldname) const
{
std::string buffer;
std::string contents;
std::ifstream fileStream(filename, std::ios::in | std::ios::binary);
if (fileStream)
{
fileStream.seekg(0, std::ios::end);
contents.resize(fileStream.tellg());
fileStream.seekg(0, std::ios::beg);
fileStream.read(&contents[0], contents.size());
fileStream.close();
}
CURL* curl = curl_easy_init();
CURLcode result;
struct curl_httppost *formpost = nullptr;
struct curl_httppost *lastptr = nullptr;
struct curl_slist *headerlist = nullptr;
static const char headerBuffer[] = "Expect:";
curl_global_init(CURL_GLOBAL_ALL);
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, "cache-control:",
CURLFORM_COPYCONTENTS, "no-cache",
CURLFORM_END);
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, "content-type:",
CURLFORM_COPYCONTENTS, "multipart/form-data",
CURLFORM_END);
std::vector<std::string> postTokens = StringAlgorithm::split(data, '&');
for (std::vector<std::string>::iterator it = postTokens.begin(); it != postTokens.end(); ++it)
{
std::vector<std::string> tokens = StringAlgorithm::split(*it, '=');
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, tokens[0].c_str(),
CURLFORM_COPYCONTENTS, tokens[1].c_str(),
CURLFORM_END);
}
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, fileFieldname.c_str(),
CURLFORM_BUFFER, "data",
CURLFORM_BUFFERPTR, contents.data(),
CURLFORM_BUFFERLENGTH, contents.size(),
CURLFORM_END);
headerlist = curl_slist_append(headerlist, headerBuffer);
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_TIMEOUT, m_timeout);
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
int code = 0;
curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
curl_easy_cleanup(curl);
curl_formfree(formpost);
curl_slist_free_all(headerlist);
if (code != 200)
{
std::stringstream error;
error << "Error (" << code << ") encountered while retrieving " << url << "\n";
error << "Data: " << buffer;
throw std::runtime_error(error.str());
}
return buffer;
}
void HttpClientImpl::GetUrlPostAttachmentSilent(const std::string& url, const std::string& data, const std::string& filename, const std::string& fileFieldname) const
{
std::string contents;
std::ifstream fileStream(filename, std::ios::in | std::ios::binary);
if (fileStream)
{
fileStream.seekg(0, std::ios::end);
contents.resize(fileStream.tellg());
fileStream.seekg(0, std::ios::beg);
fileStream.read(&contents[0], contents.size());
fileStream.close();
}
CURL* curl = curl_easy_init();
CURLcode result;
struct curl_httppost *formpost = nullptr;
struct curl_httppost *lastptr = nullptr;
struct curl_slist *headerlist = nullptr;
static const char headerBuffer[] = "Expect:";
curl_global_init(CURL_GLOBAL_ALL);
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, "cache-control:",
CURLFORM_COPYCONTENTS, "no-cache",
CURLFORM_END);
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, "content-type:",
CURLFORM_COPYCONTENTS, "multipart/form-data",
CURLFORM_END);
std::vector<std::string> postTokens = StringAlgorithm::split(data, '&');
for (std::vector<std::string>::iterator it = postTokens.begin(); it != postTokens.end(); ++it)
{
std::vector<std::string> tokens = StringAlgorithm::split(*it, '=');
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, tokens[0].c_str(),
CURLFORM_COPYCONTENTS, tokens[1].c_str(),
CURLFORM_END);
}
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, fileFieldname.c_str(),
CURLFORM_BUFFER, "data",
CURLFORM_BUFFERPTR, contents.data(),
CURLFORM_BUFFERLENGTH, contents.size(),
CURLFORM_END);
headerlist = curl_slist_append(headerlist, headerBuffer);
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_TIMEOUT, m_timeout);
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
int code = 0;
curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
curl_easy_cleanup(curl);
curl_formfree(formpost);
curl_slist_free_all(headerlist);
if (code != 200)
{
std::stringstream error;
error << "Error (" << code << ") encountered while retrieving " << url << "\n";
throw std::runtime_error(error.str());
}
}
std::string HttpClientImpl::GetUrlPostAttachmentRedirect(const std::string& url, const std::string& data, const std::string& filename, const std::string& fileFieldname) const
{
std::string contents;
std::ifstream fileStream(filename, std::ios::in | std::ios::binary);
if (fileStream)
{
fileStream.seekg(0, std::ios::end);
contents.resize(fileStream.tellg());
fileStream.seekg(0, std::ios::beg);
fileStream.read(&contents[0], contents.size());
fileStream.close();
}
CURL* curl = curl_easy_init();
CURLcode result;
struct curl_httppost *formpost = nullptr;
struct curl_httppost *lastptr = nullptr;
struct curl_slist *headerlist = nullptr;
static const char headerBuffer[] = "Expect:";
curl_global_init(CURL_GLOBAL_ALL);
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, "cache-control:",
CURLFORM_COPYCONTENTS, "no-cache",
CURLFORM_END);
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, "content-type:",
CURLFORM_COPYCONTENTS, "multipart/form-data",
CURLFORM_END);
std::vector<std::string> postTokens = StringAlgorithm::split(data, '&');
for (std::vector<std::string>::iterator it = postTokens.begin(); it != postTokens.end(); ++it)
{
std::vector<std::string> tokens = StringAlgorithm::split(*it, '=');
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, tokens[0].c_str(),
CURLFORM_COPYCONTENTS, tokens[1].c_str(),
CURLFORM_END);
}
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, fileFieldname.c_str(),
CURLFORM_BUFFER, "data",
CURLFORM_BUFFERPTR, contents.data(),
CURLFORM_BUFFERLENGTH, contents.size(),
CURLFORM_END);
headerlist = curl_slist_append(headerlist, headerBuffer);
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_TIMEOUT, m_timeout);
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
int code = 0;
curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
if (code < 300 || code >= 400)
{
curl_easy_cleanup(curl);
curl_formfree(formpost);
curl_slist_free_all(headerlist);
if (code != 200)
{
std::stringstream error;
error << "Error (" << code << ") encountered while retrieving " << url << "\n";
throw std::runtime_error(error.str());
}
return std::string();
}
char* pRedirectUrl;
curl_easy_getinfo(curl, CURLINFO_REDIRECT_URL, &pRedirectUrl);
std::string redirectUrl(pRedirectUrl);
curl_easy_cleanup(curl);
curl_formfree(formpost);
curl_slist_free_all(headerlist);
return redirectUrl;
}
std::string HttpClientImpl::GetUrlPostAttachmentContents(const std::string& url, const std::string& cookieFile, const std::string& data, const std::string& filename, const std::string& fileFieldname) const
{
std::string buffer;
std::string contents;
std::ifstream fileStream(filename, std::ios::in | std::ios::binary);
if (fileStream)
{
fileStream.seekg(0, std::ios::end);
contents.resize(fileStream.tellg());
fileStream.seekg(0, std::ios::beg);
fileStream.read(&contents[0], contents.size());
fileStream.close();
}
CURL* curl = curl_easy_init();
CURLcode result;
struct curl_httppost *formpost = nullptr;
struct curl_httppost *lastptr = nullptr;
struct curl_slist *headerlist = nullptr;
static const char headerBuffer[] = "Expect:";
curl_global_init(CURL_GLOBAL_ALL);
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, "cache-control:",
CURLFORM_COPYCONTENTS, "no-cache",
CURLFORM_END);
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, "content-type:",
CURLFORM_COPYCONTENTS, "multipart/form-data",
CURLFORM_END);
std::vector<std::string> postTokens = StringAlgorithm::split(data, '&');
for (std::vector<std::string>::iterator it = postTokens.begin(); it != postTokens.end(); ++it)
{
std::vector<std::string> tokens = StringAlgorithm::split(*it, '=');
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, tokens[0].c_str(),
CURLFORM_COPYCONTENTS, tokens[1].c_str(),
CURLFORM_END);
}
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, fileFieldname.c_str(),
CURLFORM_BUFFER, "data",
CURLFORM_BUFFERPTR, contents.data(),
CURLFORM_BUFFERLENGTH, contents.size(),
CURLFORM_END);
headerlist = curl_slist_append(headerlist, headerBuffer);
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_TIMEOUT, m_timeout);
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookieFile.c_str());
curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookieFile.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
int code = 0;
curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
curl_easy_cleanup(curl);
curl_formfree(formpost);
curl_slist_free_all(headerlist);
if (code != 200)
{
std::stringstream error;
error << "Error (" << code << ") encountered while retrieving " << url << "\n";
error << "Data: " << buffer;
throw std::runtime_error(error.str());
}
return buffer;
}
void HttpClientImpl::GetUrlPostAttachmentSilent(const std::string& url, const std::string& cookieFile, const std::string& data, const std::string& filename, const std::string& fileFieldname) const
{
std::string contents;
std::ifstream fileStream(filename, std::ios::in | std::ios::binary);
if (fileStream)
{
fileStream.seekg(0, std::ios::end);
contents.resize(fileStream.tellg());
fileStream.seekg(0, std::ios::beg);
fileStream.read(&contents[0], contents.size());
fileStream.close();
}
CURL* curl = curl_easy_init();
CURLcode result;
struct curl_httppost *formpost = nullptr;
struct curl_httppost *lastptr = nullptr;
struct curl_slist *headerlist = nullptr;
static const char headerBuffer[] = "Expect:";
curl_global_init(CURL_GLOBAL_ALL);
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, "cache-control:",
CURLFORM_COPYCONTENTS, "no-cache",
CURLFORM_END);
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, "content-type:",
CURLFORM_COPYCONTENTS, "multipart/form-data",
CURLFORM_END);
std::vector<std::string> postTokens = StringAlgorithm::split(data, '&');
for (std::vector<std::string>::iterator it = postTokens.begin(); it != postTokens.end(); ++it)
{
std::vector<std::string> tokens = StringAlgorithm::split(*it, '=');
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, tokens[0].c_str(),
CURLFORM_COPYCONTENTS, tokens[1].c_str(),
CURLFORM_END);
}
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, fileFieldname.c_str(),
CURLFORM_BUFFER, "data",
CURLFORM_BUFFERPTR, contents.data(),
CURLFORM_BUFFERLENGTH, contents.size(),
CURLFORM_END);
headerlist = curl_slist_append(headerlist, headerBuffer);
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_TIMEOUT, m_timeout);
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookieFile.c_str());
curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookieFile.c_str());
int code = 0;
curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
curl_easy_cleanup(curl);
curl_formfree(formpost);
curl_slist_free_all(headerlist);
if (code != 200)
{
std::stringstream error;
error << "Error (" << code << ") encountered while retrieving " << url << "\n";
throw std::runtime_error(error.str());
}
}
std::string HttpClientImpl::GetUrlPostAttachmentRedirect(const std::string& url, const std::string& cookieFile, const std::string& data, const std::string& filename, const std::string& fileFieldname) const
{
std::string contents;
std::ifstream fileStream(filename, std::ios::in | std::ios::binary);
if (fileStream)
{
fileStream.seekg(0, std::ios::end);
contents.resize(fileStream.tellg());
fileStream.seekg(0, std::ios::beg);
fileStream.read(&contents[0], contents.size());
fileStream.close();
}
CURL* curl = curl_easy_init();
CURLcode result;
struct curl_httppost *formpost = nullptr;
struct curl_httppost *lastptr = nullptr;
struct curl_slist *headerlist = nullptr;
static const char headerBuffer[] = "Expect:";
curl_global_init(CURL_GLOBAL_ALL);
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, "cache-control:",
CURLFORM_COPYCONTENTS, "no-cache",
CURLFORM_END);
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, "content-type:",
CURLFORM_COPYCONTENTS, "multipart/form-data",
CURLFORM_END);
std::vector<std::string> postTokens = StringAlgorithm::split(data, '&');
for (std::vector<std::string>::iterator it = postTokens.begin(); it != postTokens.end(); ++it)
{
std::vector<std::string> tokens = StringAlgorithm::split(*it, '=');
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, tokens[0].c_str(),
CURLFORM_COPYCONTENTS, tokens[1].c_str(),
CURLFORM_END);
}
curl_formadd(&formpost, &lastptr,
CURLFORM_COPYNAME, fileFieldname.c_str(),
CURLFORM_BUFFER, "data",
CURLFORM_BUFFERPTR, contents.data(),
CURLFORM_BUFFERLENGTH, contents.size(),
CURLFORM_END);
headerlist = curl_slist_append(headerlist, headerBuffer);
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_TIMEOUT, m_timeout);
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookieFile.c_str());
curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookieFile.c_str());
int code = 0;
curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
if (code < 300 || code >= 400)
{
curl_easy_cleanup(curl);
curl_formfree(formpost);
curl_slist_free_all(headerlist);
if (code != 200)
{
std::stringstream error;
error << "Error (" << code << ") encountered while retrieving " << url << "\n";
throw std::runtime_error(error.str());
}
return std::string();
}
char* pRedirectUrl;
curl_easy_getinfo(curl, CURLINFO_REDIRECT_URL, &pRedirectUrl);
std::string redirectUrl(pRedirectUrl);
curl_easy_cleanup(curl);
curl_formfree(formpost);
curl_slist_free_all(headerlist);
return redirectUrl;
}
std::string HttpClientImpl::PerformOperation(HttpClientImpl::Operation::type type, HttpClientImpl::Method::type method, const std::string& url, const std::vector<std::string> httpHeaders, const std::string& cookieFile, const std::string& data, bool returnReturnCode) const
{
std::string buffer;
std::string error;
CURL* curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
curl_easy_setopt(curl, CURLOPT_USERAGENT, m_userAgents[rand() % m_userAgents.size()].c_str());
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_TIMEOUT, m_timeout);
if (type == HttpClientImpl::Operation::Silent)
{
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, nullptr);
}
else if (type == HttpClientImpl::Operation::GetContent)
{
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
}
else if (type == HttpClientImpl::Operation::GetRedirect)
{
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 0);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, nullptr);
}
//if (method == HttpClientImpl::Method::GET)
if (method == HttpClientImpl::Method::PUT)
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
else if (method == HttpClientImpl::Method::POST)
curl_easy_setopt(curl, CURLOPT_POST, 1);
if (method != HttpClientImpl::Method::GET && !data.empty())
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());
if (!httpHeaders.empty())
{
struct curl_slist *list = nullptr;
for (auto it = httpHeaders.begin(); it != httpHeaders.end(); ++it)
list = curl_slist_append(list, it->c_str());
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
}
if (!cookieFile.empty())
{
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookieFile.c_str());
curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookieFile.c_str());
}
int code = 0;
curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code);
if (!returnReturnCode)
{
if (code < 100)
{
// Non-Existent
std::stringstream err;
err << "Error (" << code << ") encountered while retrieving " << url << "\n";
error = err.str();
}
else if (code < 200)
{
// Informational
std::stringstream info;
info << "Informational (" << code << ") encountered while retrieving " << url << "\n";
Logging::Log(Logging::Severity::Info, info.str());
}
else if (code < 300)
{
// Success
if (code == 202)
buffer = PerformOperation(type, method, url, httpHeaders, cookieFile, data);
}
else if (code < 400)
{
// Redirection
if (type == HttpClientImpl::Operation::GetRedirect)
{
char* pRedirectUrl;
curl_easy_getinfo(curl, CURLINFO_REDIRECT_URL, &pRedirectUrl);
buffer = std::string(pRedirectUrl);
}
else
{
std::stringstream redirect;
redirect << "Redirect (" << code << ") encountered while retrieving " << url << "\n";
Logging::Log(Logging::Severity::Info, redirect.str());
}
}
else if (code < 500)
{
// Client Error
std::stringstream err;
err << "Client Error (" << code << ") encountered while retrieving " << url << "\n";
err << "Response: " << buffer << "\n";
/*
if (code == 429)
{
// Too Many Requests
curl_off_t wait = 0;
curl_easy_getinfo(curl, CURLINFO_RETRY_AFTER, &wait);
err << "Retry after " << wait << " seconds\n";
}
*/
error = err.str();
}
else if (code < 600)
{
// Server Error
std::stringstream err;
err << "Server Error (" << code << ") encountered while retrieving " << url << "\n";
err << "Response: " << buffer << "\n";
error = err.str();
}
else
{
// Non-Existent
std::stringstream err;
err << "Error (" << code << ") encountered while retrieving " << url << "\n";
err << "Response: " << buffer << "\n";
error = err.str();
}
}
else
{
buffer = std::to_string(code);
}
curl_easy_cleanup(curl);
if (!error.empty())
throw std::runtime_error(error);
return buffer;
}
size_t HttpClientImpl::WriteCallback(char* data, size_t size, size_t nmemb, std::string* writerData)
{
if (writerData == nullptr)
return size * nmemb;
writerData->append(data, size * nmemb);
return size * nmemb;
}
} // namespace Http