瀏覽代碼

Simplify HttpClient Interface

JDierkse 5 年之前
父節點
當前提交
c1951f0e4d

+ 4 - 154
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<std::string>& httpHeaders) const
-{
-	return m_pHttpClientImpl->GetUrlContents(url, httpHeaders);
-}
-
-void HttpClient::GetUrlSilent(const std::string& url, const std::vector<std::string>& httpHeaders) const
-{
-	m_pHttpClientImpl->GetUrlSilent(url, httpHeaders);
-}
-
-std::string HttpClient::GetUrlRedirect(const std::string& url, const std::vector<std::string>& 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<std::string>& httpHeaders, const std::string& cookieFile) const
-{
-	return m_pHttpClientImpl->GetUrlContents(url, httpHeaders, cookieFile);
-}
-
-void HttpClient::GetUrlSilent(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& cookieFile) const
-{
-	m_pHttpClientImpl->GetUrlSilent(url, httpHeaders, cookieFile);
-}
-
-std::string HttpClient::GetUrlRedirect(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& cookieFile) const
-{
-	return m_pHttpClientImpl->GetUrlRedirect(url, httpHeaders, cookieFile);
-}
-
-std::string HttpClient::PutUrlContents(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& data) const
-{
-	return m_pHttpClientImpl->PutUrlContents(url, httpHeaders, data);
-}
-
-void HttpClient::PutUrlSilent(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& data) const
-{
-	m_pHttpClientImpl->PutUrlSilent(url, httpHeaders, data);
-}
-
-std::string HttpClient::PutUrlRedirect(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& data) const
-{
-	return m_pHttpClientImpl->PutUrlRedirect(url, httpHeaders, data);
-}
-
-std::string HttpClient::PutUrlContents(const std::string& url, const std::vector<std::string>& 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<std::string>& 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<std::string>& 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<std::string>& httpHeaders, const std::string& data) const
-{
-	return m_pHttpClientImpl->GetUrlPostContents(url, httpHeaders, data);
-}
-
-void HttpClient::GetUrlPostSilent(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& data) const
-{
-	m_pHttpClientImpl->GetUrlPostSilent(url, httpHeaders, data);
-}
-
-std::string HttpClient::GetUrlPostRedirect(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& data) const
-{
-	return m_pHttpClientImpl->GetUrlPostRedirect(url, httpHeaders, data);
-}
-
-std::string HttpClient::GetUrlPostContents(const std::string& url, const std::vector<std::string>& 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<std::string>& 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<std::string>& 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

+ 250 - 577
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,534 +27,265 @@ 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(), 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);
-
-	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<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);
-
-	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<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);
-
-	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)
-		{
-			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);
+	if (!request.Filename().empty() ||
+	    !request.FileFieldname().empty())
+	{
+		if (request.Filename().empty() ||
+		    request.FileFieldname().empty())
+		{
+			std::stringstream error;
+			error << "Incomplete File Upload, missing filename or filefieldname";
+			throw std::runtime_error(error.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 (request.Method() != HttpRequest::Method::POST)
+		{
+			std::stringstream error;
+			error << "Incompatible File Upload, method must be POST";
+			throw std::runtime_error(error.str());
+		}
 
-	if (code != 200)
-	{
-		std::stringstream error;
-		error << "Error (" << code << ") encountered while retrieving " << url << "\n";
-		error << "Data: " << buffer;
-		throw std::runtime_error(error.str());
+		return ProcessFileUpload(request);
 	}
 
-	return buffer;
+	return PerformOperation(request);
 }
 
-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 HttpClientImpl::PerformOperation(const HttpRequest& request) const
 {
-	std::string contents;
-	std::ifstream fileStream(filename, std::ios::in | std::ios::binary);
+	std::stringstream debug;
 
-	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();
-	}
+	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();
-	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_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);
 
-	curl_formadd(&formpost, &lastptr,
-		CURLFORM_COPYNAME, "content-type:",
-		CURLFORM_COPYCONTENTS, "multipart/form-data",
-		CURLFORM_END);
+	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 (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 (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("");
 
-	std::vector<std::string> postTokens = StringAlgorithm::split(data, '&');
+	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("");
 
-	for (std::vector<std::string>::iterator it = postTokens.begin(); it != postTokens.end(); ++it)
+	if (method != HttpRequest::Method::GET &&
+	    method != HttpRequest::Method::HEAD &&
+	    !data.empty())
 	{
-		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_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("");
 
-	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());
+			debug << "Header: " << header << std::endl;
+		}
 
-	headerlist = curl_slist_append(headerlist, headerBuffer);
+		curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
+	}
+	if (m_debugLogging)
+		Logging::Log(Logging::Severity::Debug, debug.str());
+	debug.str("");
 
-	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());
+	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);
-	curl_easy_cleanup(curl);
-	curl_formfree(formpost);
-	curl_slist_free_all(headerlist);
 
-	if (code != 200)
+	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);
+				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
 	{
-		std::stringstream error;
-		error << "Error (" << code << ") encountered while retrieving " << url << "\n";
-		throw std::runtime_error(error.str());
+		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::GetUrlPostAttachmentRedirect(const std::string& url, const std::string& cookieFile, const std::string& data, const std::string& filename, const std::string& fileFieldname) const
+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);
 
@@ -566,13 +298,8 @@ std::string HttpClientImpl::GetUrlPostAttachmentRedirect(const std::string& url,
 		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);
 
@@ -605,105 +332,50 @@ std::string HttpClientImpl::GetUrlPostAttachmentRedirect(const std::string& url,
 		CURLFORM_BUFFERLENGTH, contents.size(),
 		CURLFORM_END);
 
-	headerlist = curl_slist_append(headerlist, headerBuffer);
+	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);
-	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)
+	if (!cookieFile.empty())
 	{
-		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();
+		curl_easy_setopt(curl, CURLOPT_COOKIEFILE, cookieFile.c_str());
+		curl_easy_setopt(curl, CURLOPT_COOKIEJAR, cookieFile.c_str());
 	}
 
-	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)
+	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 (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);
 	}
-	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);
 	}
 
-	//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());
-	}
-
 	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 +395,12 @@ 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);
@@ -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);

+ 6 - 64
Http/HttpClientImpl.h

@@ -1,6 +1,7 @@
 #ifndef HTTP_HTTPCLIENTIMPL_H
 #define HTTP_HTTPCLIENTIMPL_H
 
+#include "HttpClient.h"
 #include <string>
 #include <vector>
 
@@ -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<std::string>& httpHeaders) const;
-	void GetUrlSilent(const std::string& url, const std::vector<std::string>& httpHeaders) const;
-	std::string GetUrlRedirect(const std::string& url, const std::vector<std::string>& 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<std::string>& httpHeaders,  const std::string& cookieFile) const;
-	void GetUrlSilent(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& cookieFile) const;
-	std::string GetUrlRedirect(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& cookieFile) const;
-
-	std::string PutUrlContents(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& data) const;
-	void PutUrlSilent(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& data) const;
-	std::string PutUrlRedirect(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& data) const;
-
-	std::string PutUrlContents(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& cookieFile, const std::string& data) const;
-	void PutUrlSilent(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& cookieFile, const std::string& data) const;
-	std::string PutUrlRedirect(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& cookieFile, const std::string& data) const;
-
-	std::string GetUrlPostContents(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& data) const;
-	void GetUrlPostSilent(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& data) const;
-	std::string GetUrlPostRedirect(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& data) const;
-
-	std::string GetUrlPostContents(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& cookieFile, const std::string& data) const;
-	void GetUrlPostSilent(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& cookieFile, const std::string& data) const;
-	std::string GetUrlPostRedirect(const std::string& url, const std::vector<std::string>& 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
-		};
-	};
-
-	struct Operation
-	{
-		enum type
-		{
-			Silent,
-			GetContent,
-			GetRedirect
-		};
-	};
+	std::string PerformOperation(const HttpRequest& request) const;
+	std::string ProcessFileUpload(const HttpRequest& request) const;
 
-private:
-	std::string PerformOperation(HttpClientImpl::Operation::type type, HttpClientImpl::Method::type method, const std::string& url, const std::vector<std::string> httpHeaders = std::vector<std::string>(), 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<std::string> m_userAgents;
 };
 

+ 2 - 2
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 <asio.hpp>
@@ -40,7 +40,7 @@ private:
 	Buffer m_data;
 	std::tuple<Tribool::Tribool, Buffer::iterator> m_dataState;
 	bool m_dataIncomplete;
-	HttpRequest m_request;
+	Internal::HttpRequest m_request;
 	HttpRequestParser m_requestParser;
 };
 

+ 97 - 0
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<std::string> HttpRequest::Headers() const
+{
+	return m_headers;
+}
+
+void HttpRequest::Headers(const std::vector<std::string>& 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

+ 1 - 1
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))

+ 2 - 2
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 <functional>
@@ -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<HttpPostData> GetPostData(const std::string& boundary, const std::string& data) const;

+ 1 - 1
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)
 	{

+ 3 - 3
Http/HttpRequestParser.h

@@ -1,7 +1,7 @@
 #ifndef HTTP_HTTPREQUESTPARSER_H
 #define HTTP_HTTPREQUESTPARSER_H
 
-#include "HttpRequest.h"
+#include "Internal/HttpRequest.h"
 #include <Tribool.h>
 #include <tuple>
 
@@ -18,7 +18,7 @@ public:
 	void Reset();
 
 	template <typename InputIterator>
-	std::tuple<Tribool::Tribool, InputIterator> Parse(HttpRequest& request, InputIterator begin, InputIterator end)
+	std::tuple<Tribool::Tribool, InputIterator> 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);

+ 6 - 4
Http/HttpRequest.h → 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 <string>
 
 
 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

+ 1 - 0
Http/Internal/Makefile

@@ -0,0 +1 @@
+../Makefile

+ 3 - 42
include/HttpClient.h

@@ -1,6 +1,7 @@
 #ifndef HTTPCLIENT_H
 #define HTTPCLIENT_H
 
+#include "HttpRequest.h"
 #include <memory>
 #include <string>
 #include <vector>
@@ -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<std::string>& httpHeaders) const;
-	void GetUrlSilent(const std::string& url, const std::vector<std::string>& httpHeaders) const;
-	std::string GetUrlRedirect(const std::string& url, const std::vector<std::string>& 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<std::string>& httpHeaders,  const std::string& cookieFile) const;
-	void GetUrlSilent(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& cookieFile) const;
-	std::string GetUrlRedirect(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& cookieFile) const;
-
-	std::string PutUrlContents(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& data) const;
-	void PutUrlSilent(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& data) const;
-	std::string PutUrlRedirect(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& data) const;
-
-	std::string PutUrlContents(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& cookieFile, const std::string& data) const;
-	void PutUrlSilent(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& cookieFile, const std::string& data) const;
-	std::string PutUrlRedirect(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& cookieFile, const std::string& data) const;
-
-	std::string GetUrlPostContents(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& data) const;
-	void GetUrlPostSilent(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& data) const;
-	std::string GetUrlPostRedirect(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& data) const;
-
-	std::string GetUrlPostContents(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& cookieFile, const std::string& data) const;
-	void GetUrlPostSilent(const std::string& url, const std::vector<std::string>& httpHeaders, const std::string& cookieFile, const std::string& data) const;
-	std::string GetUrlPostRedirect(const std::string& url, const std::vector<std::string>& 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<HttpClientImpl> m_pHttpClientImpl;

+ 79 - 0
include/HttpRequest.h

@@ -0,0 +1,79 @@
+#ifndef HTTPREQUEST_H
+#define HTTPREQUEST_H
+
+#include <string>
+#include <vector>
+
+
+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<std::string> Headers() const;
+	void Headers(const std::vector<std::string>& 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<std::string> m_headers;
+	std::string m_data;
+
+	std::string m_cookieFile;
+
+	std::string m_filename;
+	std::string m_fileFieldname;
+};
+
+} // namespace Http
+
+#endif // HTTPREQUEST_H