micfox
8/2/2017 - 12:24 AM

Curl_client.h

#include <string>
#include "curl/curl.h"
#include <iostream>

using std::cout;
using std::endl;
using std::string;

struct Global_initializer {
	Global_initializer() {
		curl_global_init(CURL_GLOBAL_ALL);
	}
	~Global_initializer() {
		curl_global_cleanup();
	}
};

class Curl_client {
	const static Global_initializer gi;
	string url;
	CURL *curl;
	CURLcode res;
	struct curl_slist *header_list = nullptr;

	static size_t OnWriteData(void* buffer, size_t size, size_t nmemb, void* lpVoid)
	{
		std::string* str = dynamic_cast<std::string*>((std::string *)lpVoid);
		if (NULL == str || NULL == buffer)
		{
			return -1;
		}

		char* pData = (char*)buffer;
		str->append(pData, size * nmemb);
		return nmemb;
	}

	static int debug_callback(CURL *, curl_infotype itype, char * pData, size_t size, void *)
	{
		if (itype == CURLINFO_TEXT)
		{
			//printf("[TEXT]%s\n", pData);  
		}
		else if (itype == CURLINFO_HEADER_IN)
		{
			printf("[HEADER_IN]%s\n", pData);
		}
		else if (itype == CURLINFO_HEADER_OUT)
		{

			printf("[HEADER_OUT]%s\n", pData);
		}
		else if (itype == CURLINFO_DATA_IN)
		{
			// can't see plainly if Data is gzip encoded
			printf("[DATA_IN]%s\n", pData);
		}
		else if (itype == CURLINFO_DATA_OUT)
		{
			//printf("[DATA_OUT]%s\n", pData);
		}
		return 0;
	}
	
public:
	static bool debug;
	string resp;
	long resp_code;
	Curl_client(string url) {
		this->url = url;
		curl = curl_easy_init();
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, &resp);
		if (debug) {
			curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
			curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, debug_callback);
		}
	}
	~Curl_client() {
		curl_easy_cleanup(curl);
		if (header_list) curl_slist_free_all(header_list);
	}
	CURLcode get() {
		resp.clear();
		if (header_list) curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list);
		curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
		res = curl_easy_perform(curl);
		if (res != CURLE_OK)
		{
			cout << "visit " << url << " failed: " <<
					 curl_easy_strerror(res) << endl;
		}

		curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &resp_code);
		return res;
	}
	CURLcode post(const string& post_data = string()) {
		resp.clear();

		header_list = curl_slist_append(header_list, "Expect:");  // remove 100 continue
		curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list);

		curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
		curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data.c_str());
		res = curl_easy_perform(curl);
		if (res != CURLE_OK)
		{
			cout << "visit " << url << " failed: " <<
				curl_easy_strerror(res) << endl;
		}

		curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &resp_code);
		return res;
	}
	Curl_client& enable_debug() {
		curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
		curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, debug_callback);
		return *this;
	}
	Curl_client& set_proxy(const string& proxy) {
		curl_easy_setopt(curl, CURLOPT_PROXY, proxy.c_str());
		return *this;
	}
	Curl_client& ignore_ssl_cert() {
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, false);
		return *this;
	}

	template<typename T>
	Curl_client& setopt(CURLoption option, T value) {
		curl_easy_setopt(curl, option, value);
		return *this;
	}

	Curl_client& append_header(const string& header) {
		header_list = curl_slist_append(header_list, header.c_str());
		return *this;
	}

	Curl_client& remove_header(const string& header) {
		append_header(header + ':');
		return *this;
	}

	// accept "identity" "deflate" "gzip"
	Curl_client& set_encoding(const char* encode) {
		curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, encode);
		return *this;
	}
};

const Global_initializer Curl_client::gi{};
bool Curl_client::debug{ false };