#include "Request.h" #include "Response.h" #include "curl/curl.h" #include #include #include #include #include #include #include namespace { static size_t WriteMemoryCallback(char *contents, size_t size, size_t nmemb, void *userp) { size_t realsize = size * nmemb; std::string *str = (std::string *)userp; if (realsize) { str->append(contents); } return realsize; } } Request::Request() : mCurl(NULL), mHeaders(NULL), mVerbose(false), mValid(true) { mCurl = curl_easy_init(); if (!mCurl) { mValid = false; } } Request::~Request() { if (mCurl) { curl_easy_cleanup(mCurl); } if (mHeaders) { curl_slist_free_all((struct curl_slist *)mHeaders); } } void Request::setClientCertificate(const std::string &cerPath, const std::string &keyPath) { if (!mValid) { return; } mCert = cerPath; mKey = keyPath; curl_easy_setopt(mCurl, CURLOPT_SSLCERT, cerPath.data()); curl_easy_setopt(mCurl, CURLOPT_SSLKEY, keyPath.data()); } void Request::setVerbose(bool verbose) { mVerbose = verbose; } Response Request::post(const std::string &url, const std::string &body, const std::unordered_map &headers) { if (!mValid) { return Response::ErrorResponse("http handle not valid!"); } if (url.empty()) { return Response::ErrorResponse("post error, url is empty!"); } int protocolIdx = url.find_first_of("http"); if (protocolIdx < 0) { return Response::ErrorResponse("not http protocal find in the url!"); } curl_easy_setopt(mCurl, CURLOPT_URL, url.data()); // https设置 if (url.length() > protocolIdx + 5 && url[protocolIdx + 4] == 's') { // 避免使用本地ca curl_easy_setopt(mCurl, CURLOPT_SSL_VERIFYPEER, 0L); // 关于host名验证,便于直接使用ip地址访问!!! curl_easy_setopt(mCurl, CURLOPT_SSL_VERIFYHOST, 0L); } curl_easy_setopt(mCurl, CURLOPT_POST, 1L); // CURLOPT_POSTFIELDS 不可以为空不然会有问题 if (body.empty()) { curl_easy_setopt(mCurl, CURLOPT_POSTFIELDS, ""); } else { curl_easy_setopt(mCurl, CURLOPT_POSTFIELDS, body.data()); } // set headers if (!headers.empty()) { for (auto item : headers) { std::string header; header.append(item.first); header.append(": "); header.append(item.second); mHeaders = curl_slist_append((struct curl_slist *)mHeaders, header.data()); } curl_easy_setopt(mCurl, CURLOPT_HTTPHEADER, mHeaders); } Response resp; curl_easy_setopt(mCurl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); curl_easy_setopt(mCurl, CURLOPT_WRITEDATA, (void *)&(resp.getContent())); curl_easy_setopt(mCurl, CURLOPT_TIMEOUT, 6L); curl_easy_setopt(mCurl, CURLOPT_CONNECTTIMEOUT, 6L); if (mVerbose) { curl_easy_setopt(mCurl, CURLOPT_VERBOSE, 1L); } CURLcode res; /* Perform the request, res will get the return code */ res = curl_easy_perform(mCurl); if (mHeaders) { curl_slist_free_all((struct curl_slist *)mHeaders); mHeaders = NULL; } /* Check for errors */ if (res != CURLE_OK) { char buffer[4096] = {0}; sprintf(buffer, "post failed because do curl_easy_perform() failed:%s \n", curl_easy_strerror(res)); return Response::ErrorResponse(buffer); } long response_code; curl_easy_getinfo(mCurl, CURLINFO_RESPONSE_CODE, &response_code); resp.setHttpCode(response_code); return std::move(resp); } void Request::Init() { curl_global_init(CURL_GLOBAL_ALL); } void Request::Dispose() { curl_global_cleanup(); }