CurlHttp.cpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. #include "CurlHttp.h"
  2. #include <regex>
  3. #include "fmtlog.h"
  4. /* ==================================================================================
  5. * *********************************** 全局变量 *************************************
  6. * ================================================================================== */
  7. /* ==================================================================================
  8. * *********************************** 全局函数 *************************************
  9. * ================================================================================== */
  10. /**
  11. * @brief 写入回调函数
  12. *
  13. * @param contents 接收到的内容
  14. * @param size 内容大小,单位size_t
  15. * @param nmemb size_t的单位
  16. * @param userp 用户传入的接收区指针
  17. * @return size_t
  18. */
  19. static size_t WriteStringCallback(void* contents, size_t size, size_t nmemb, std::string* userStr)
  20. {
  21. size_t newLength = size * nmemb;
  22. size_t oldLength = userStr->size();
  23. try
  24. {
  25. userStr->resize(oldLength + newLength);
  26. }
  27. catch(std::bad_alloc &e)
  28. {
  29. FMTLOG_ERROR("{}", e.what());
  30. return 0;
  31. }
  32. std::copy_n((char*)contents, newLength, userStr->begin() + oldLength);
  33. return size * nmemb;
  34. }
  35. /* ==================================================================================
  36. * *********************************** 成员函数 *************************************
  37. * ================================================================================== */
  38. CurlHttp::CurlHttp()
  39. {
  40. curl_global_init(CURL_GLOBAL_DEFAULT);
  41. }
  42. CurlHttp::~CurlHttp()
  43. {
  44. curl_global_cleanup();
  45. }
  46. /**
  47. * @brief 获取信息
  48. *
  49. * @param url 网址
  50. * @param response 返回的数据
  51. * @return true
  52. * @return false
  53. */
  54. bool CurlHttp::Get(const std::string& url, std::string& response)
  55. {
  56. CURL *curl;
  57. CURLcode res;
  58. curl = curl_easy_init();
  59. if(curl == nullptr)
  60. {
  61. FMTLOG_ERROR("curl_easy_init() failed");
  62. return false;
  63. }
  64. /* 设置为Get请求 */
  65. curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
  66. /* 设置url */
  67. curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
  68. /* 设置重定向,遇到3xx返回值时自动重定向 */
  69. curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
  70. /* 设置https协议 */
  71. curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "https");
  72. /* 设置写入回调函数 */
  73. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteStringCallback);
  74. curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
  75. /* 设置超时 */
  76. curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L);
  77. curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L);
  78. /* 发送请求 */
  79. bool result = true;
  80. res = curl_easy_perform(curl);
  81. if(res != CURLE_OK)
  82. {
  83. FMTLOG_ERROR("Get failed: {}, Url: {}", curl_easy_strerror(res), url);
  84. result = false;
  85. }
  86. curl_easy_cleanup(curl);
  87. return true;
  88. }
  89. /* 获取信息,带有http头 */
  90. bool CurlHttp::Get(const std::string& url, const std::vector<std::string>& vecHeader, std::string& response)
  91. {
  92. CURL *curl;
  93. CURLcode res;
  94. curl = curl_easy_init();
  95. if(curl == nullptr)
  96. {
  97. FMTLOG_ERROR("curl_easy_init() failed");
  98. return false;
  99. }
  100. /* 设置为Get请求 */
  101. curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
  102. /* 设置url */
  103. curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
  104. /* 设置http头 */
  105. struct curl_slist *headers = NULL;
  106. if(!vecHeader.empty())
  107. {
  108. for(auto &header : vecHeader)
  109. {
  110. headers = curl_slist_append(headers, header.c_str());
  111. }
  112. curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
  113. }
  114. /* 设置重定向,遇到3xx返回值时自动重定向 */
  115. curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
  116. /* 设置https协议 */
  117. curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "https");
  118. /* 设置写入回调函数 */
  119. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteStringCallback);
  120. curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
  121. /* 设置超时 */
  122. curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L);
  123. curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L);
  124. /* 发送请求 */
  125. bool result = true;
  126. res = curl_easy_perform(curl);
  127. if(res != CURLE_OK)
  128. {
  129. FMTLOG_ERROR("Get failed: {}, Url:{}", curl_easy_strerror(res), url);
  130. result = false;
  131. }
  132. /* 清理内存 */
  133. curl_slist_free_all(headers);
  134. curl_easy_cleanup(curl);
  135. return result;
  136. }
  137. /**
  138. * @brief 发送信息,不携带http头
  139. *
  140. * @param url
  141. * @param postData
  142. * @param response
  143. * @return true
  144. * @return false
  145. */
  146. bool CurlHttp::Post(const std::string& url, const std::string& postData, std::string& response)
  147. {
  148. CURL *curl;
  149. CURLcode res;
  150. curl = curl_easy_init();
  151. if(curl == nullptr)
  152. {
  153. FMTLOG_ERROR("curl_easy_init() failed");
  154. return false;
  155. }
  156. /* 设置用户名密码,可能有的话 */
  157. /* 设置动作功能和网址 */
  158. curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
  159. curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
  160. /* 设置重定向,遇到3xx返回值时自动重定向 */
  161. curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
  162. /* 设置https协议 */
  163. curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "http");
  164. /* 设置包体 */
  165. curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData.c_str());
  166. curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, postData.size());
  167. /* 设置回调函数 */
  168. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteStringCallback);
  169. curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
  170. /* 设置连接超时和接收数据超时 */
  171. curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L);
  172. curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L);
  173. /* 设置不发送任何信号,对于多线程有用 */
  174. // curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
  175. /* 发送请求 */
  176. res = curl_easy_perform(curl);
  177. bool result = true;
  178. if(res != CURLE_OK)
  179. {
  180. FMTLOG_ERROR("Post failed: {}, Url: {}", curl_easy_strerror(res), url);
  181. result = false;
  182. }
  183. /* 清理curl */
  184. curl_easy_cleanup(curl);
  185. return result;
  186. }
  187. /**
  188. * @brief 发送带有Http头和包体的信息
  189. *
  190. * @param url 网址
  191. * @param vecHeader http头,vector<string>格式,每个元素为一行,
  192. * 如 User-Agent: Apifox/1.0.0 (https://apifox.com)
  193. * @param postData 发送的包体
  194. * @param response 返回的数据
  195. * @return true
  196. * @return false
  197. */
  198. bool CurlHttp::Post(const std::string& url,const std::vector<std::string>& vecHeader, const std::string& postData, std::string& response)
  199. {
  200. if(url.size() < 8)
  201. {
  202. FMTLOG_ERROR("url error, url size less 8");
  203. }
  204. CURL *curl;
  205. CURLcode res;
  206. curl = curl_easy_init();
  207. if(curl == nullptr)
  208. {
  209. FMTLOG_ERROR("curl_easy_init() failed");
  210. return false;
  211. }
  212. /* 设置动作功能和网址 */
  213. curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
  214. curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
  215. /* 设置重定向,遇到3xx返回值时自动重定向 */
  216. curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
  217. /* 设置https协议,自动判断是http还是https */
  218. std::string strUrlPre;
  219. if(url.rfind("http://", 0) == 0)
  220. {
  221. strUrlPre = "http";
  222. }
  223. else if(url.rfind("https://", 0) == 0)
  224. {
  225. strUrlPre = "https";
  226. }
  227. curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, strUrlPre.c_str());
  228. /* 设置http头 */
  229. struct curl_slist *headers = NULL;
  230. if(!vecHeader.empty())
  231. {
  232. for(auto &header : vecHeader)
  233. {
  234. headers = curl_slist_append(headers, header.c_str());
  235. }
  236. curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
  237. }
  238. /* 设置包体 */
  239. curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData.c_str());
  240. curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, postData.size());
  241. /* 设置回调函数 */
  242. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteStringCallback);
  243. curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
  244. /* 设置连接超时和接收数据超时 */
  245. curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30L);
  246. curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L);
  247. /* 设置不发送任何信号,对于多线程有用 */
  248. // curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
  249. /* 发送请求 */
  250. res = curl_easy_perform(curl);
  251. bool result = true;
  252. if(res != CURLE_OK)
  253. {
  254. FMTLOG_ERROR("Post failed: {}, Url: {}", curl_easy_strerror(res), url);
  255. result = false;
  256. }
  257. curl_slist_free_all(headers);
  258. /* 清理curl */
  259. curl_easy_cleanup(curl);
  260. return result;
  261. }