diff --git a/Http/HttpClient.cpp b/Http/HttpClient.cpp index 4da8b86..bc03ab4 100644 --- a/Http/HttpClient.cpp +++ b/Http/HttpClient.cpp @@ -4,166 +4,16 @@ namespace Http { -HttpClient::HttpClient(int timeout) : - m_pHttpClientImpl(new HttpClientImpl(timeout)) +HttpClient::HttpClient(int timeout, bool debugLogging) : + m_pHttpClientImpl(new HttpClientImpl(timeout, debugLogging)) { } HttpClient::~HttpClient() = default; -int HttpClient::GetUrlReturnCode(const std::string& url) const +std::string HttpClient::Open(const HttpRequest& request) const { - return m_pHttpClientImpl->GetUrlReturnCode(url); -} - -std::string HttpClient::GetUrlContents(const std::string& url) const -{ - return m_pHttpClientImpl->GetUrlContents(url); -} - -void HttpClient::GetUrlSilent(const std::string& url) const -{ - m_pHttpClientImpl->GetUrlSilent(url); -} - -std::string HttpClient::GetUrlRedirect(const std::string& url) const -{ - return m_pHttpClientImpl->GetUrlRedirect(url); -} - -std::string HttpClient::GetUrlContents(const std::string& url, const std::vector& httpHeaders) const -{ - return m_pHttpClientImpl->GetUrlContents(url, httpHeaders); -} - -void HttpClient::GetUrlSilent(const std::string& url, const std::vector& httpHeaders) const -{ - m_pHttpClientImpl->GetUrlSilent(url, httpHeaders); -} - -std::string HttpClient::GetUrlRedirect(const std::string& url, const std::vector& httpHeaders) const -{ - return m_pHttpClientImpl->GetUrlRedirect(url, httpHeaders); -} - -std::string HttpClient::GetUrlContents(const std::string& url, const std::string& cookieFile) const -{ - return m_pHttpClientImpl->GetUrlContents(url, cookieFile); -} - -void HttpClient::GetUrlSilent(const std::string& url, const std::string& cookieFile) const -{ - m_pHttpClientImpl->GetUrlSilent(url, cookieFile); -} - -std::string HttpClient::GetUrlRedirect(const std::string& url, const std::string& cookieFile) const -{ - return m_pHttpClientImpl->GetUrlRedirect(url, cookieFile); -} - -std::string HttpClient::GetUrlContents(const std::string& url, const std::vector& httpHeaders, const std::string& cookieFile) const -{ - return m_pHttpClientImpl->GetUrlContents(url, httpHeaders, cookieFile); -} - -void HttpClient::GetUrlSilent(const std::string& url, const std::vector& httpHeaders, const std::string& cookieFile) const -{ - m_pHttpClientImpl->GetUrlSilent(url, httpHeaders, cookieFile); -} - -std::string HttpClient::GetUrlRedirect(const std::string& url, const std::vector& httpHeaders, const std::string& cookieFile) const -{ - return m_pHttpClientImpl->GetUrlRedirect(url, httpHeaders, cookieFile); -} - -std::string HttpClient::PutUrlContents(const std::string& url, const std::vector& httpHeaders, const std::string& data) const -{ - return m_pHttpClientImpl->PutUrlContents(url, httpHeaders, data); -} - -void HttpClient::PutUrlSilent(const std::string& url, const std::vector& httpHeaders, const std::string& data) const -{ - m_pHttpClientImpl->PutUrlSilent(url, httpHeaders, data); -} - -std::string HttpClient::PutUrlRedirect(const std::string& url, const std::vector& httpHeaders, const std::string& data) const -{ - return m_pHttpClientImpl->PutUrlRedirect(url, httpHeaders, data); -} - -std::string HttpClient::PutUrlContents(const std::string& url, const std::vector& httpHeaders, const std::string& cookieFile, const std::string& data) const -{ - return m_pHttpClientImpl->PutUrlContents(url, httpHeaders, cookieFile, data); -} - -void HttpClient::PutUrlSilent(const std::string& url, const std::vector& httpHeaders, const std::string& cookieFile, const std::string& data) const -{ - m_pHttpClientImpl->PutUrlSilent(url, httpHeaders, cookieFile, data); -} - -std::string HttpClient::PutUrlRedirect(const std::string& url, const std::vector& httpHeaders, const std::string& cookieFile, const std::string& data) const -{ - return m_pHttpClientImpl->PutUrlRedirect(url, httpHeaders, cookieFile, data); -} - -std::string HttpClient::GetUrlPostContents(const std::string& url, const std::vector& httpHeaders, const std::string& data) const -{ - return m_pHttpClientImpl->GetUrlPostContents(url, httpHeaders, data); -} - -void HttpClient::GetUrlPostSilent(const std::string& url, const std::vector& httpHeaders, const std::string& data) const -{ - m_pHttpClientImpl->GetUrlPostSilent(url, httpHeaders, data); -} - -std::string HttpClient::GetUrlPostRedirect(const std::string& url, const std::vector& httpHeaders, const std::string& data) const -{ - return m_pHttpClientImpl->GetUrlPostRedirect(url, httpHeaders, data); -} - -std::string HttpClient::GetUrlPostContents(const std::string& url, const std::vector& httpHeaders, const std::string& cookieFile, const std::string& data) const -{ - return m_pHttpClientImpl->GetUrlPostContents(url, httpHeaders, cookieFile, data); -} - -void HttpClient::GetUrlPostSilent(const std::string& url, const std::vector& httpHeaders, const std::string& cookieFile, const std::string& data) const -{ - m_pHttpClientImpl->GetUrlPostSilent(url, httpHeaders, cookieFile, data); -} - -std::string HttpClient::GetUrlPostRedirect(const std::string& url, const std::vector& httpHeaders, const std::string& cookieFile, const std::string& data) const -{ - return m_pHttpClientImpl->GetUrlPostRedirect(url, httpHeaders, cookieFile, data); -} - -std::string HttpClient::GetUrlPostAttachmentContents(const std::string& url, const std::string& data, const std::string& filename, const std::string& fileFieldname) const -{ - return m_pHttpClientImpl->GetUrlPostAttachmentContents(url, data, filename, fileFieldname); -} - -void HttpClient::GetUrlPostAttachmentSilent(const std::string& url, const std::string& data, const std::string& filename, const std::string& fileFieldname) const -{ - m_pHttpClientImpl->GetUrlPostAttachmentSilent(url, data, filename, fileFieldname); -} - -std::string HttpClient::GetUrlPostAttachmentRedirect(const std::string& url, const std::string& data, const std::string& filename, const std::string& fileFieldname) const -{ - return m_pHttpClientImpl->GetUrlPostAttachmentRedirect(url, data, filename, fileFieldname); -} - -std::string HttpClient::GetUrlPostAttachmentContents(const std::string& url, const std::string& cookieFile, const std::string& data, const std::string& filename, const std::string& fileFieldname) const -{ - return m_pHttpClientImpl->GetUrlPostAttachmentContents(url, cookieFile, data, filename, fileFieldname); -} - -void HttpClient::GetUrlPostAttachmentSilent(const std::string& url, const std::string& cookieFile, const std::string& data, const std::string& filename, const std::string& fileFieldname) const -{ - m_pHttpClientImpl->GetUrlPostAttachmentSilent(url, cookieFile, data, filename, fileFieldname); -} - -std::string HttpClient::GetUrlPostAttachmentRedirect(const std::string& url, const std::string& cookieFile, const std::string& data, const std::string& filename, const std::string& fileFieldname) const -{ - return m_pHttpClientImpl->GetUrlPostAttachmentRedirect(url, cookieFile, data, filename, fileFieldname); + return m_pHttpClientImpl->Open(request); } } // namespace Http diff --git a/Http/HttpClientImpl.cpp b/Http/HttpClientImpl.cpp index 0bc4112..be15223 100644 --- a/Http/HttpClientImpl.cpp +++ b/Http/HttpClientImpl.cpp @@ -10,8 +10,9 @@ namespace Http { -HttpClientImpl::HttpClientImpl(int timeout) : - m_timeout(timeout) +HttpClientImpl::HttpClientImpl(int timeout, bool debugLogging) : + m_timeout(timeout), + m_debugLogging(debugLogging) { curl_global_init(CURL_GLOBAL_ALL); @@ -26,625 +27,43 @@ HttpClientImpl::~HttpClientImpl() curl_global_cleanup(); } -int HttpClientImpl::GetUrlReturnCode(const std::string& url) const +std::string HttpClientImpl::Open(const HttpRequest& request) const { - return std::stoi(PerformOperation(HttpClientImpl::Operation::Silent, HttpClientImpl::Method::GET, url, std::vector(), 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& httpHeaders) const -{ - return PerformOperation(HttpClientImpl::Operation::GetContent, HttpClientImpl::Method::GET, url, httpHeaders); -} - -void HttpClientImpl::GetUrlSilent(const std::string& url, const std::vector& httpHeaders) const -{ - PerformOperation(HttpClientImpl::Operation::Silent, HttpClientImpl::Method::GET, url, httpHeaders); -} - -std::string HttpClientImpl::GetUrlRedirect(const std::string& url, const std::vector& 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(), cookieFile); -} - -void HttpClientImpl::GetUrlSilent(const std::string& url, const std::string& cookieFile) const -{ - PerformOperation(HttpClientImpl::Operation::Silent, HttpClientImpl::Method::GET, url, std::vector(), 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(), cookieFile); -} - -std::string HttpClientImpl::GetUrlContents(const std::string& url, const std::vector& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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) + if (!request.Filename().empty() || + !request.FileFieldname().empty()) { - 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 postTokens = StringAlgorithm::split(data, '&'); - - for (std::vector::iterator it = postTokens.begin(); it != postTokens.end(); ++it) - { - std::vector 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); - - long 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 postTokens = StringAlgorithm::split(data, '&'); - - for (std::vector::iterator it = postTokens.begin(); it != postTokens.end(); ++it) - { - std::vector 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); - - long 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 postTokens = StringAlgorithm::split(data, '&'); - - for (std::vector::iterator it = postTokens.begin(); it != postTokens.end(); ++it) - { - std::vector 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); - - long 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) + if (request.Filename().empty() || + request.FileFieldname().empty()) { std::stringstream error; - error << "Error (" << code << ") encountered while retrieving " << url << "\n"; + error << "Incomplete File Upload, missing filename or filefieldname"; 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 postTokens = StringAlgorithm::split(data, '&'); - - for (std::vector::iterator it = postTokens.begin(); it != postTokens.end(); ++it) - { - std::vector 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); - - long 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 postTokens = StringAlgorithm::split(data, '&'); - - for (std::vector::iterator it = postTokens.begin(); it != postTokens.end(); ++it) - { - std::vector 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()); - - long 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 postTokens = StringAlgorithm::split(data, '&'); - - for (std::vector::iterator it = postTokens.begin(); it != postTokens.end(); ++it) - { - std::vector 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()); - - long 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) + if (request.Method() != HttpRequest::Method::POST) { std::stringstream error; - error << "Error (" << code << ") encountered while retrieving " << url << "\n"; + error << "Incompatible File Upload, method must be POST"; throw std::runtime_error(error.str()); } - return std::string(); + return ProcessFileUpload(request); } - 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; + return PerformOperation(request); } -std::string HttpClientImpl::PerformOperation(HttpClientImpl::Operation::type type, HttpClientImpl::Method::type method, const std::string& url, const std::vector httpHeaders, const std::string& cookieFile, const std::string& data, bool returnReturnCode) const +std::string HttpClientImpl::PerformOperation(const HttpRequest& request) const { + std::stringstream debug; + + auto method = request.Method(); + auto returnType = request.ReturnType(); + auto url = request.URL(); + auto headers = request.Headers(); + auto data = request.Data(); + auto cookieFile = request.CookieFile(); + std::string buffer; std::string error; CURL* curl = curl_easy_init(); @@ -656,54 +75,113 @@ std::string HttpClientImpl::PerformOperation(HttpClientImpl::Operation::type typ curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl, CURLOPT_TIMEOUT, m_timeout); - if (type == HttpClientImpl::Operation::Silent) + if (returnType == HttpRequest::ReturnType::None || + returnType == HttpRequest::ReturnType::Code) { curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, nullptr); + debug << "ReturnType::None || ReturnType::Code" << std::endl; } - else if (type == HttpClientImpl::Operation::GetContent) + else if (returnType == HttpRequest::ReturnType::Content) { curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer); + debug << "ReturnType::Content" << std::endl; } - else if (type == HttpClientImpl::Operation::GetRedirect) + else if (returnType == HttpRequest::ReturnType::Redirect) { curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 0); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, nullptr); + debug << "ReturnType::Content" << std::endl; } + if (m_debugLogging) + Logging::Log(Logging::Severity::Debug, debug.str()); + debug.str(""); - //if (method == HttpClientImpl::Method::GET) - if (method == HttpClientImpl::Method::PUT) - curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT"); - else if (method == HttpClientImpl::Method::POST) + if (method == HttpRequest::Method::HEAD) + { + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "HEAD"); + debug << "Method::HEAD" << std::endl; + } + else if (method == HttpRequest::Method::POST) + { curl_easy_setopt(curl, CURLOPT_POST, 1); + debug << "Method::POST" << std::endl; + } + else if (method == HttpRequest::Method::PUT) + { + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT"); + debug << "Method::PUT" << std::endl; + } + else if (method == HttpRequest::Method::DELETE) + { + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE"); + debug << "Method::DELETE" << std::endl; + } + else if (method == HttpRequest::Method::CONNECT) + { + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "CONNECT"); + debug << "Method::CONNECT" << std::endl; + } + else if (method == HttpRequest::Method::TRACE) + { + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "TRACE"); + debug << "Method::TRACE" << std::endl; + } + else if (method == HttpRequest::Method::PATCH) + { + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PATCH"); + debug << "Method::PATCH" << std::endl; + } + if (m_debugLogging) + Logging::Log(Logging::Severity::Debug, debug.str()); + debug.str(""); + + if (method != HttpRequest::Method::GET && + method != HttpRequest::Method::HEAD && + !data.empty()) + { - if (method != HttpClientImpl::Method::GET && !data.empty()) curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str()); + debug << "Data: " << data << std::endl; + } + if (m_debugLogging) + Logging::Log(Logging::Severity::Debug, debug.str()); + debug.str(""); - if (!httpHeaders.empty()) + if (!headers.empty()) { struct curl_slist *list = nullptr; - for (auto it = httpHeaders.begin(); it != httpHeaders.end(); ++it) - list = curl_slist_append(list, it->c_str()); + for (const auto& header : headers) + { + list = curl_slist_append(list, header.c_str()); + debug << "Header: " << header << std::endl; + } curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list); } + if (m_debugLogging) + Logging::Log(Logging::Severity::Debug, debug.str()); + debug.str(""); if (!cookieFile.empty()) { curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookieFile.c_str()); curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookieFile.c_str()); + debug << "CookieFile: " << cookieFile << std::endl; } + if (m_debugLogging) + Logging::Log(Logging::Severity::Debug, debug.str()); + debug.str(""); long code = 0; curl_easy_perform(curl); curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code); - if (!returnReturnCode) + if (returnType != HttpRequest::ReturnType::Code) { if (code < 100) { @@ -723,12 +201,206 @@ std::string HttpClientImpl::PerformOperation(HttpClientImpl::Operation::type typ { // Success if (code == 202) - buffer = PerformOperation(type, method, url, httpHeaders, cookieFile, data); + buffer = PerformOperation(request); } else if (code < 400) { // Redirection - if (type == HttpClientImpl::Operation::GetRedirect) + if (returnType == HttpRequest::ReturnType::Redirect) + { + 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); + } + + debug << "Code: " << code << std::endl; + if (m_debugLogging) + Logging::Log(Logging::Severity::Debug, debug.str()); + debug.str(""); + + curl_easy_cleanup(curl); + + if (!error.empty()) + throw std::runtime_error(error); + + return buffer; +} + +std::string HttpClientImpl::ProcessFileUpload(const HttpRequest& request) const +{ + auto method = request.Method(); + auto returnType = request.ReturnType(); + auto url = request.URL(); + auto headers = request.Headers(); + auto data = request.Data(); + auto cookieFile = request.CookieFile(); + auto filename = request.Filename(); + auto fileFieldname = request.FileFieldname(); + + std::string buffer; + std::string error; + CURL* curl = curl_easy_init(); + + 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(); + } + + struct curl_httppost *formpost = nullptr; + struct curl_httppost *lastptr = nullptr; + + 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 postTokens = StringAlgorithm::split(data, '&'); + + for (std::vector::iterator it = postTokens.begin(); it != postTokens.end(); ++it) + { + std::vector 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); + + if (!headers.empty()) + { + struct curl_slist *list = nullptr; + for (const auto& header : headers) + list = curl_slist_append(list, header.c_str()); + + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list); + } + + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, m_timeout); + curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); + + if (!cookieFile.empty()) + { + curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookieFile.c_str()); + curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookieFile.c_str()); + } + + if (returnType == HttpRequest::ReturnType::None || + returnType == HttpRequest::ReturnType::Code) + { + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteCallback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, nullptr); + } + else if (returnType == HttpRequest::ReturnType::Content) + { + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteCallback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer); + } + else if (returnType == HttpRequest::ReturnType::Redirect) + { + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 0); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteCallback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, nullptr); + } + + long code = 0; + curl_easy_perform(curl); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code); + + if (returnType != HttpRequest::ReturnType::Code) + { + 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(request); + } + else if (code < 400) + { + // Redirection + if (returnType == HttpRequest::ReturnType::Redirect) { char* pRedirectUrl; curl_easy_getinfo(curl, CURLINFO_REDIRECT_URL, &pRedirectUrl); @@ -781,6 +453,7 @@ std::string HttpClientImpl::PerformOperation(HttpClientImpl::Operation::type typ } curl_easy_cleanup(curl); + curl_formfree(formpost); if (!error.empty()) throw std::runtime_error(error); diff --git a/Http/HttpClientImpl.h b/Http/HttpClientImpl.h index 29b7f62..64c3a0f 100644 --- a/Http/HttpClientImpl.h +++ b/Http/HttpClientImpl.h @@ -1,6 +1,7 @@ #ifndef HTTP_HTTPCLIENTIMPL_H #define HTTP_HTTPCLIENTIMPL_H +#include "HttpClient.h" #include #include @@ -12,81 +13,22 @@ namespace Http { class HttpClientImpl { public: - HttpClientImpl(int timeout); + HttpClientImpl(int timeout, bool debugLogging); ~HttpClientImpl(); HttpClientImpl(const HttpClientImpl&) = delete; - int GetUrlReturnCode(const std::string& url) const; - - std::string GetUrlContents(const std::string& url) const; - void GetUrlSilent(const std::string& url) const; - std::string GetUrlRedirect(const std::string& url) const; - - std::string GetUrlContents(const std::string& url, const std::vector& httpHeaders) const; - void GetUrlSilent(const std::string& url, const std::vector& httpHeaders) const; - std::string GetUrlRedirect(const std::string& url, const std::vector& httpHeaders) const; - - std::string GetUrlContents(const std::string& url, const std::string& cookieFile) const; - void GetUrlSilent(const std::string& url, const std::string& cookieFile) const; - std::string GetUrlRedirect(const std::string& url, const std::string& cookieFile) const; - - std::string GetUrlContents(const std::string& url, const std::vector& httpHeaders, const std::string& cookieFile) const; - void GetUrlSilent(const std::string& url, const std::vector& httpHeaders, const std::string& cookieFile) const; - std::string GetUrlRedirect(const std::string& url, const std::vector& httpHeaders, const std::string& cookieFile) const; - - std::string PutUrlContents(const std::string& url, const std::vector& httpHeaders, const std::string& data) const; - void PutUrlSilent(const std::string& url, const std::vector& httpHeaders, const std::string& data) const; - std::string PutUrlRedirect(const std::string& url, const std::vector& httpHeaders, const std::string& data) const; - - std::string PutUrlContents(const std::string& url, const std::vector& httpHeaders, const std::string& cookieFile, const std::string& data) const; - void PutUrlSilent(const std::string& url, const std::vector& httpHeaders, const std::string& cookieFile, const std::string& data) const; - std::string PutUrlRedirect(const std::string& url, const std::vector& httpHeaders, const std::string& cookieFile, const std::string& data) const; - - std::string GetUrlPostContents(const std::string& url, const std::vector& httpHeaders, const std::string& data) const; - void GetUrlPostSilent(const std::string& url, const std::vector& httpHeaders, const std::string& data) const; - std::string GetUrlPostRedirect(const std::string& url, const std::vector& httpHeaders, const std::string& data) const; - - std::string GetUrlPostContents(const std::string& url, const std::vector& httpHeaders, const std::string& cookieFile, const std::string& data) const; - void GetUrlPostSilent(const std::string& url, const std::vector& httpHeaders, const std::string& cookieFile, const std::string& data) const; - std::string GetUrlPostRedirect(const std::string& url, const std::vector& httpHeaders, const std::string& cookieFile, const std::string& data) const; - - std::string GetUrlPostAttachmentContents(const std::string& url, const std::string& data, const std::string& filename, const std::string& fileFieldname) const; - void GetUrlPostAttachmentSilent(const std::string& url, const std::string& data, const std::string& filename, const std::string& fileFieldname) const; - std::string GetUrlPostAttachmentRedirect(const std::string& url, const std::string& data, const std::string& filename, const std::string& fileFieldname) const; - - std::string GetUrlPostAttachmentContents(const std::string& url, const std::string& cookieFile, const std::string& data, const std::string& filename, const std::string& fileFieldname) const; - void GetUrlPostAttachmentSilent(const std::string& url, const std::string& cookieFile, const std::string& data, const std::string& filename, const std::string& fileFieldname) const; - std::string GetUrlPostAttachmentRedirect(const std::string& url, const std::string& cookieFile, const std::string& data, const std::string& filename, const std::string& fileFieldname) const; + std::string Open(const HttpRequest& request) const; private: - struct Method - { - enum type - { - GET, - PUT, - POST - }; - }; + std::string PerformOperation(const HttpRequest& request) const; + std::string ProcessFileUpload(const HttpRequest& request) const; - struct Operation - { - enum type - { - Silent, - GetContent, - GetRedirect - }; - }; - -private: - std::string PerformOperation(HttpClientImpl::Operation::type type, HttpClientImpl::Method::type method, const std::string& url, const std::vector httpHeaders = std::vector(), const std::string& cookieFile = std::string(), const std::string& data = std::string(), bool returnCode = false) const; - void ThrowException(int code); static size_t WriteCallback(char* data, size_t size, size_t nmemb, std::string* writerData); private: int m_timeout; + bool m_debugLogging; std::vector m_userAgents; }; diff --git a/Http/HttpConnection.h b/Http/HttpConnection.h index c4e32fa..a5d8fe5 100644 --- a/Http/HttpConnection.h +++ b/Http/HttpConnection.h @@ -2,7 +2,7 @@ #define HTTP_HTTPCONNECTION_H #include "HttpReply.h" -#include "HttpRequest.h" +#include "Internal/HttpRequest.h" #include "HttpRequestHandler.h" #include "HttpRequestParser.h" #include @@ -40,7 +40,7 @@ private: Buffer m_data; std::tuple m_dataState; bool m_dataIncomplete; - HttpRequest m_request; + Internal::HttpRequest m_request; HttpRequestParser m_requestParser; }; diff --git a/Http/HttpRequest.cpp b/Http/HttpRequest.cpp new file mode 100644 index 0000000..27a284b --- /dev/null +++ b/Http/HttpRequest.cpp @@ -0,0 +1,97 @@ +#include "HttpRequest.h" + + +namespace Http { + +HttpRequest::HttpRequest(const std::string url) : + m_method(HttpRequest::Method::GET), + m_returnType(HttpRequest::ReturnType::Content), + m_url(url) +{ +} + +HttpRequest::~HttpRequest() +{ +} + +HttpRequest::Method::type HttpRequest::Method() const +{ + return m_method; +} + +void HttpRequest::Method(HttpRequest::Method::type method) +{ + m_method = method; +} + +HttpRequest::ReturnType::type HttpRequest::ReturnType() const +{ + return m_returnType; +} + +void HttpRequest::ReturnType(HttpRequest::ReturnType::type returnType) +{ + m_returnType = returnType; +} + +std::string HttpRequest::URL() const +{ + return m_url; +} + +void HttpRequest::URL(const std::string& url) +{ + m_url = url; +} + +std::vector HttpRequest::Headers() const +{ + return m_headers; +} + +void HttpRequest::Headers(const std::vector& headers) +{ + m_headers = headers; +} + +std::string HttpRequest::Data() const +{ + return m_data; +} + +void HttpRequest::Data(const std::string& data) +{ + m_data = data; +} + +std::string HttpRequest::CookieFile() const +{ + return m_cookieFile; +} + +void HttpRequest::CookieFile(const std::string& cookieFile) +{ + m_cookieFile = cookieFile; +} + +std::string HttpRequest::Filename() const +{ + return m_filename; +} + +void HttpRequest::Filename(const std::string& filename) +{ + m_filename = filename; +} + +std::string HttpRequest::FileFieldname() const +{ + return m_fileFieldname; +} + +void HttpRequest::FileFieldname(const std::string& fileFieldname) +{ + m_fileFieldname = fileFieldname; +} + +} // namespace Http diff --git a/Http/HttpRequestHandler.cpp b/Http/HttpRequestHandler.cpp index a8f98cb..028555e 100644 --- a/Http/HttpRequestHandler.cpp +++ b/Http/HttpRequestHandler.cpp @@ -12,7 +12,7 @@ HttpRequestHandler::HttpRequestHandler(HttpServer::CallbackMethod callback) : { } -HttpReply HttpRequestHandler::HandleRequest(const HttpRequest& request, const std::string& data) +HttpReply HttpRequestHandler::HandleRequest(const Internal::HttpRequest& request, const std::string& data) { std::string requestPath; if (!URLDecode(request.uri, requestPath)) diff --git a/Http/HttpRequestHandler.h b/Http/HttpRequestHandler.h index d156fcd..cc4200e 100644 --- a/Http/HttpRequestHandler.h +++ b/Http/HttpRequestHandler.h @@ -2,7 +2,7 @@ #define HTTP_HTTPREQUESTHANDLER_H #include "HttpReply.h" -#include "HttpRequest.h" +#include "Internal/HttpRequest.h" #include "HttpPostData.h" #include "HttpServer.h" #include @@ -19,7 +19,7 @@ public: HttpRequestHandler(const HttpRequestHandler&) = delete; - HttpReply HandleRequest(const HttpRequest& request, const std::string& data); + HttpReply HandleRequest(const Internal::HttpRequest& request, const std::string& data); private: std::vector GetPostData(const std::string& boundary, const std::string& data) const; diff --git a/Http/HttpRequestParser.cpp b/Http/HttpRequestParser.cpp index e8432b6..7e0756c 100644 --- a/Http/HttpRequestParser.cpp +++ b/Http/HttpRequestParser.cpp @@ -14,7 +14,7 @@ void HttpRequestParser::Reset() m_state = State::MethodStart; } -Tribool::Tribool HttpRequestParser::Consume(HttpRequest& request, char input) +Tribool::Tribool HttpRequestParser::Consume(Internal::HttpRequest& request, char input) { switch (m_state) { diff --git a/Http/HttpRequestParser.h b/Http/HttpRequestParser.h index 1f67fb0..cf7e7f0 100644 --- a/Http/HttpRequestParser.h +++ b/Http/HttpRequestParser.h @@ -1,7 +1,7 @@ #ifndef HTTP_HTTPREQUESTPARSER_H #define HTTP_HTTPREQUESTPARSER_H -#include "HttpRequest.h" +#include "Internal/HttpRequest.h" #include #include @@ -18,7 +18,7 @@ public: void Reset(); template - std::tuple Parse(HttpRequest& request, InputIterator begin, InputIterator end) + std::tuple Parse(Internal::HttpRequest& request, InputIterator begin, InputIterator end) { Tribool::Tribool result = Tribool::Tribool::Indeterminate; while (begin != end) @@ -32,7 +32,7 @@ public: } private: - Tribool::Tribool Consume(HttpRequest& request, char input); + Tribool::Tribool Consume(Internal::HttpRequest& request, char input); static bool IsChar(int c); static bool IsCtl(int c); static bool IsTSpecial(int c); diff --git a/Http/HttpRequest.h b/Http/Internal/HttpRequest.h similarity index 50% rename from Http/HttpRequest.h rename to Http/Internal/HttpRequest.h index 3de5e4c..d9a4162 100644 --- a/Http/HttpRequest.h +++ b/Http/Internal/HttpRequest.h @@ -1,11 +1,12 @@ -#ifndef HTTP_HTTPREQUEST_H -#define HTTP_HTTPREQUEST_H +#ifndef HTTP_INTERNAL_HTTPREQUEST_H +#define HTTP_INTERNAL_HTTPREQUEST_H -#include "HttpHeaders.h" +#include "Http/HttpHeaders.h" #include namespace Http { +namespace Internal { struct HttpRequest { @@ -16,6 +17,7 @@ struct HttpRequest HttpHeaders headers; }; +} // namespace Internal } // namespace Http -#endif // HTTP_HTTPREQUEST_H +#endif // HTTP_INTERNAL_HTTPREQUEST_H diff --git a/Http/Internal/Makefile b/Http/Internal/Makefile new file mode 120000 index 0000000..d0b0e8e --- /dev/null +++ b/Http/Internal/Makefile @@ -0,0 +1 @@ +../Makefile \ No newline at end of file diff --git a/include/HttpClient.h b/include/HttpClient.h index d61f62a..c3f1d88 100644 --- a/include/HttpClient.h +++ b/include/HttpClient.h @@ -1,6 +1,7 @@ #ifndef HTTPCLIENT_H #define HTTPCLIENT_H +#include "HttpRequest.h" #include #include #include @@ -13,52 +14,12 @@ class HttpClientImpl; class HttpClient { public: - HttpClient(int timeout = 3); + HttpClient(int timeout = 3, bool debugLogging = false); ~HttpClient(); HttpClient(const HttpClient&) = delete; - int GetUrlReturnCode(const std::string& url) const; - - std::string GetUrlContents(const std::string& url) const; - void GetUrlSilent(const std::string& url) const; - std::string GetUrlRedirect(const std::string& url) const; - - std::string GetUrlContents(const std::string& url, const std::vector& httpHeaders) const; - void GetUrlSilent(const std::string& url, const std::vector& httpHeaders) const; - std::string GetUrlRedirect(const std::string& url, const std::vector& httpHeaders) const; - - std::string GetUrlContents(const std::string& url, const std::string& cookieFile) const; - void GetUrlSilent(const std::string& url, const std::string& cookieFile) const; - std::string GetUrlRedirect(const std::string& url, const std::string& cookieFile) const; - - std::string GetUrlContents(const std::string& url, const std::vector& httpHeaders, const std::string& cookieFile) const; - void GetUrlSilent(const std::string& url, const std::vector& httpHeaders, const std::string& cookieFile) const; - std::string GetUrlRedirect(const std::string& url, const std::vector& httpHeaders, const std::string& cookieFile) const; - - std::string PutUrlContents(const std::string& url, const std::vector& httpHeaders, const std::string& data) const; - void PutUrlSilent(const std::string& url, const std::vector& httpHeaders, const std::string& data) const; - std::string PutUrlRedirect(const std::string& url, const std::vector& httpHeaders, const std::string& data) const; - - std::string PutUrlContents(const std::string& url, const std::vector& httpHeaders, const std::string& cookieFile, const std::string& data) const; - void PutUrlSilent(const std::string& url, const std::vector& httpHeaders, const std::string& cookieFile, const std::string& data) const; - std::string PutUrlRedirect(const std::string& url, const std::vector& httpHeaders, const std::string& cookieFile, const std::string& data) const; - - std::string GetUrlPostContents(const std::string& url, const std::vector& httpHeaders, const std::string& data) const; - void GetUrlPostSilent(const std::string& url, const std::vector& httpHeaders, const std::string& data) const; - std::string GetUrlPostRedirect(const std::string& url, const std::vector& httpHeaders, const std::string& data) const; - - std::string GetUrlPostContents(const std::string& url, const std::vector& httpHeaders, const std::string& cookieFile, const std::string& data) const; - void GetUrlPostSilent(const std::string& url, const std::vector& httpHeaders, const std::string& cookieFile, const std::string& data) const; - std::string GetUrlPostRedirect(const std::string& url, const std::vector& httpHeaders, const std::string& cookieFile, const std::string& data) const; - - std::string GetUrlPostAttachmentContents(const std::string& url, const std::string& data, const std::string& filename, const std::string& fileFieldname) const; - void GetUrlPostAttachmentSilent(const std::string& url, const std::string& data, const std::string& filename, const std::string& fileFieldname) const; - std::string GetUrlPostAttachmentRedirect(const std::string& url, const std::string& data, const std::string& filename, const std::string& fileFieldname) const; - - std::string GetUrlPostAttachmentContents(const std::string& url, const std::string& cookieFile, const std::string& data, const std::string& filename, const std::string& fileFieldname) const; - void GetUrlPostAttachmentSilent(const std::string& url, const std::string& cookieFile, const std::string& data, const std::string& filename, const std::string& fileFieldname) const; - std::string GetUrlPostAttachmentRedirect(const std::string& url, const std::string& cookieFile, const std::string& data, const std::string& filename, const std::string& fileFieldname) const; + std::string Open(const HttpRequest& request) const; private: std::unique_ptr m_pHttpClientImpl; diff --git a/include/HttpRequest.h b/include/HttpRequest.h new file mode 100644 index 0000000..dd2e7cd --- /dev/null +++ b/include/HttpRequest.h @@ -0,0 +1,79 @@ +#ifndef HTTPREQUEST_H +#define HTTPREQUEST_H + +#include +#include + + +namespace Http { + +class HttpRequest +{ +public: + struct Method + { + enum type + { + GET, + HEAD, + POST, + PUT, + DELETE, + CONNECT, + TRACE, + PATCH + }; + }; + + struct ReturnType + { + enum type + { + None, + Code, + Content, + Redirect + }; + }; + +public: + HttpRequest(const std::string url); + ~HttpRequest(); + + HttpRequest::Method::type Method() const; + void Method(HttpRequest::Method::type method); + HttpRequest::ReturnType::type ReturnType() const; + void ReturnType(HttpRequest::ReturnType::type returnType); + + std::string URL() const; + void URL(const std::string& url); + std::vector Headers() const; + void Headers(const std::vector& headers); + std::string Data() const; + void Data(const std::string& data); + + std::string CookieFile() const; + void CookieFile(const std::string& cookieFile); + + std::string Filename() const; + void Filename(const std::string& filename); + std::string FileFieldname() const; + void FileFieldname(const std::string& fileFieldname); + +private: + HttpRequest::Method::type m_method; + HttpRequest::ReturnType::type m_returnType; + + std::string m_url; + std::vector m_headers; + std::string m_data; + + std::string m_cookieFile; + + std::string m_filename; + std::string m_fileFieldname; +}; + +} // namespace Http + +#endif // HTTPREQUEST_H