1 #pragma once
2
3 #include <string>
4
5 #include "libcurl/include/curl/curl.h"
6
7 class HTTPClient
8 {
9 /**
10 *
11 * http操作
12 *
13 */
14 enum class ACTION : uint8_t
15 {
16 GET,
17 POST,
18 };
19
20 public:
21 /**
22 *
23 * 析构函数
24 *
25 */
26 ~HTTPClient()
27 {
28 Clear();
29 }
30
31 /**
32 *
33 * get操作
34 *
35 * @return 是否处理成功
36 *
37 */
38 bool Get()
39 {
40 return Launch(ACTION::GET);
41 }
42
43 /**
44 *
45 * post操作
46 *
47 * @return 是否处理成功
48 *
49 */
50 bool Post()
51 {
52 return Launch(ACTION::POST);
53 }
54
55 /**
56 *
57 * 端口
58 *
59 * @return 端口
60 *
61 */
62 const uint16_t Port() const
63 {
64 return _port;
65 }
66
67 /**
68 *
69 * 最后一次错误信息
70 *
71 * @return 最后一次错误信息
72 *
73 */
74 const char * LastError() const
75 {
76 return curl_easy_strerror(_code);
77 }
78
79 /**
80 *
81 * 域名
82 *
83 * @return 域名
84 *
85 */
86 const std::string & Url() const
87 {
88 return _url;
89 }
90
91 /**
92 *
93 * 帐号
94 *
95 * @return 帐号
96 *
97 */
98 const std::string & User() const
99 {
100 return _user;
101 }
102
103 /**
104 *
105 * 密码
106 *
107 * @return 密码
108 *
109 */
110 const std::string & Pass() const
111 {
112 return _pass;
113 }
114
115 /**
116 *
117 * 登陆信息
118 *
119 * @return 登陆信息
120 *
121 */
122 const std::string & Login() const
123 {
124 return _login;
125 }
126
127 /**
128 *
129 * 参数
130 *
131 * @return 参数
132 *
133 */
134 const std::string & Params() const
135 {
136 return _params;
137 }
138
139 /**
140 *
141 * 响应数据
142 *
143 * @return 响应数据
144 *
145 */
146 const std::string & Response() const
147 {
148 return _response;
149 }
150
151 /**
152 *
153 * 设置端口
154 *
155 * @param port 端口
156 *
157 */
158 void SetPort(const uint16_t port)
159 {
160 _port = port;
161 }
162
163 /**
164 *
165 * 设置域名
166 *
167 * @param url 域名
168 *
169 */
170 void SetUrl(const std::string & url)
171 {
172 _url = url;
173 }
174
175 /**
176 *
177 * 设置帐号
178 *
179 * @param user 帐号
180 *
181 */
182 void SetUser(const std::string & user)
183 {
184 _user = user;
185 }
186
187 /**
188 *
189 * 设置密码
190 *
191 * @param pass 密码
192 *
193 */
194 void SetPass(const std::string & pass)
195 {
196 _pass = pass;
197 }
198
199 /**
200 *
201 * 设置登陆信息
202 *
203 * @param user 帐号
204 * @param pass 密码
205 *
206 */
207 void SetLogin(const std::string & user, const std::string & pass)
208 {
209 SetUser(user);
210 SetPass(pass);
211
212 _login += user;
213 _login += ":";
214 _login += pass;
215 }
216
217 /**
218 *
219 * 设置参数
220 *
221 * @param param 参数
222 *
223 */
224 void SetParam(const std::string & param)
225 {
226 _params = param;
227 }
228
229 /**
230 *
231 * 添加头部信息
232 *
233 * @param header 头部信息
234 *
235 */
236 void AddHeader(const char * header)
237 {
238 _headers = curl_slist_append(_headers, header);
239 }
240
241 /**
242 * 添加参数
243 *
244 * @param param 参数
245 *
246 */
247 void AddParam(const std::string & param)
248 {
249 _params += param;
250 }
251
252 /**
253 *
254 * 添加参数
255 *
256 * @param key 关键字
257 * @param value 数值
258 *
259 */
260 void AddParam(const std::string & key, const std::string & value)
261 {
262 if (!_params.empty())
263 {
264 _params += "&";
265 }
266
267 _params += key;
268 _params += "=";
269 _params += value;
270 }
271
272 /**
273 *
274 * 清空数据
275 *
276 */
277 void Clear()
278 {
279 ClearPort();
280 ClearLogin();
281 ClearError();
282 ClearParams();
283 ClearHeader();
284 ClearResponse();
285 }
286
287 /**
288 *
289 * 清空端口
290 *
291 */
292 void ClearPort()
293 {
294 _port = 0;
295 }
296
297 /**
298 *
299 * 清空登陆信息
300 *
301 */
302 void ClearLogin()
303 {
304 _user.clear();
305 _pass.clear();
306 _login.clear();
307 }
308
309 /**
310 *
311 * 清空错误信息
312 *
313 */
314 void ClearError()
315 {
316 _code = CURLE_OK;
317 }
318
319 /**
320 *
321 * 清空参数
322 *
323 */
324 void ClearParams()
325 {
326 _params.clear();
327 }
328
329 /**
330 *
331 * 清空头部信息
332 *
333 */
334 void ClearHeader()
335 {
336 if (_headers)
337 {
338 curl_slist_free_all(_headers);
339
340 _headers = nullptr;
341 }
342 }
343
344 /**
345 *
346 * 清空响应数据
347 *
348 */
349 void ClearResponse()
350 {
351 _response.clear();
352 }
353
354 protected:
355 /**
356 *
357 * 处理http
358 *
359 * @param action http操作类型
360 *
361 * @return 是否处理成功
362 *
363 */
364 bool Launch(ACTION action)
365 {
366 ClearError();
367 ClearResponse();
368
369 CURL * handle = curl_easy_init();
370
371 if (handle == nullptr)
372 {
373 _code = CURLE_FAILED_INIT;
374
375 return false;
376 }
377
378 if (action == ACTION::POST)
379 {
380 curl_easy_setopt(handle, CURLOPT_POST, 1);
381
382 if (!_params.empty())
383 {
384 curl_easy_setopt(handle, CURLOPT_POSTFIELDS, _params.data());
385 curl_easy_setopt(handle, CURLOPT_POSTFIELDSIZE, _params.size());
386 }
387 }
388
389 if (_port > 0)
390 {
391 curl_easy_setopt(handle, CURLOPT_PORT, _port);
392 }
393
394 if (!_login.empty())
395 {
396 curl_easy_setopt(handle, CURLOPT_USERPWD, _login.c_str());
397 }
398
399 if (_headers)
400 {
401 curl_easy_setopt(handle, CURLOPT_HTTPHEADER, _headers);
402 }
403
404 curl_easy_setopt(handle, CURLOPT_VERBOSE, 0L);
405 curl_easy_setopt(handle, CURLOPT_HTTPAUTH, CURLSSH_AUTH_ANY);
406 curl_easy_setopt(handle, CURLOPT_URL, _url.data());
407
408 curl_easy_setopt(handle, CURLOPT_WRITEDATA, &_response);
409 curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, RespondFunction);
410
411 #if 0
412 curl_easy_setopt(handle, CURLOPT_READDATA, NULL);
413 curl_easy_setopt(handle, CURLOPT_READFUNCTION, NULL);
414
415 curl_easy_setopt(handle, CURLOPT_HEADERDATA, NULL);
416 curl_easy_setopt(handle, CURLOPT_HEADERFUNCTION, NULL);
417 #endif
418
419 // https不验证证书
420 curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0L);
421 // https不验证HOST
422 curl_easy_setopt(handle, CURLOPT_SSL_VERIFYHOST, 0L);
423
424 // 当多个线程都使用超时处理的时候, 同时主线程中有sleep或是wait等操作. 如果不设置这个选项, libcurl将会发信号打断wait从而导致程序退出.
425 curl_easy_setopt(handle, CURLOPT_NOSIGNAL, 1);
426 // 查找次数,防止查找太深
427 curl_easy_setopt(handle, CURLOPT_MAXREDIRS, 1);
428 // 返回的头部中有Location(一般直接请求的url没找到), 则继续请求Location对应的数据
429 curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1);
430
431 //接收数据时超时设置
432 curl_easy_setopt(handle, CURLOPT_TIMEOUT, 2);
433 // 连接超时
434 curl_easy_setopt(handle, CURLOPT_CONNECTTIMEOUT, 2);
435
436 _code = curl_easy_perform(handle);
437
438 curl_easy_cleanup(handle);
439
440 return _code == CURLE_OK;
441 }
442
443 /**
444 *
445 * 响应回调函数
446 *
447 * @param buffer 响应数据缓冲区
448 * @param size 响应数据块大小
449 * @param nmemb 响应数据块个数
450 * @param stream 存储响应数据地址
451 *
452 * @return 读取响应数据个数
453 *
454 */
455 static size_t RespondFunction(void * buffer, size_t size, size_t nmemb, void * stream)
456 {
457 auto str = dynamic_cast<std::string *>((std::string *)stream);
458
459 if (str == nullptr)
460 {
461 return 0;
462 }
463
464 auto realSize = nmemb * size;
465
466 str->append((const char *)buffer, realSize);
467
468 return realSize;
469 }
470
471 protected:
472 CURLcode _code{ CURLE_OK };
473
474 uint16_t _port{ 0 };
475
476 std::string _url{};
477 std::string _user{};
478 std::string _pass{};
479 std::string _login{};
480 std::string _params{};
481 std::string _response{};
482
483 struct curl_slist * _headers{ nullptr };
484 };