155 lines
3.9 KiB
C++
155 lines
3.9 KiB
C++
#include "Request.h"
|
||
#include "Response.h"
|
||
#include "curl/curl.h"
|
||
#include <algorithm>
|
||
#include <cstddef>
|
||
#include <cstdio>
|
||
#include <exception>
|
||
#include <new>
|
||
#include <stdexcept>
|
||
#include <string>
|
||
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<std::string, std::string> &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();
|
||
} |