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 };