HTTPHelper - 副本.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. #include "StdAfx.h"
  2. #include "HTTPHelper.h"
  3. HTTPHelper::HTTPHelper(void):m_hSession(NULL),m_hConnect(NULL),m_hRequest(NULL),m_nRetryTimes(3)
  4. {
  5. }
  6. HTTPHelper::~HTTPHelper(void)
  7. {
  8. }
  9. bool HTTPHelper::UrlParse(std::wstring strUrl)
  10. {
  11. int nPos = 0;
  12. m_strUrl = strUrl;
  13. std::wstring strSub;
  14. wchar_t* magic[] = { L"https://", L"http://", NULL };
  15. if ( m_strUrl.find(magic[0]) != std::wstring::npos || m_strUrl.find(magic[1]) != std::wstring::npos ) {
  16. if (m_strUrl.find(magic[0]) != std::wstring::npos) {
  17. m_dwPort = 443;
  18. m_brequireValidSSL=TRUE;
  19. strSub = m_strUrl.substr(8);
  20. } else {
  21. m_dwPort = 80;
  22. m_brequireValidSSL=FALSE;
  23. strSub = m_strUrl.substr(7);
  24. }
  25. if ( (nPos = strSub.find(L"/")) != std::wstring::npos ) {
  26. m_strDomain = strSub.substr(0, nPos);
  27. m_strParam = strSub.substr(nPos);
  28. } else {
  29. m_strDomain = strSub;
  30. m_strParam = L"/";
  31. }
  32. if ( (nPos = m_strDomain.find(L":")) != std::wstring::npos ) {
  33. m_strHost = m_strDomain.substr(0, nPos);
  34. m_dwPort = _wtol(m_strDomain.substr(nPos+1).c_str());
  35. } else {
  36. m_strHost = m_strDomain;
  37. }
  38. return TRUE;
  39. }
  40. return FALSE;
  41. }
  42. bool HTTPHelper::GetHtml(HTTPITEM &item, HTTPRESULT &result)
  43. {
  44. if ( !SendRequest(item,result) )
  45. return false;
  46. return true;
  47. }
  48. bool HTTPHelper::SendRequest(HTTPITEM &item,HTTPRESULT &httpResult)
  49. {
  50. DWORD dwError = -1;
  51. if ( m_hSession == NULL ) {
  52. // 创建会话;
  53. m_hSession = WinHttpOpen(
  54. item.m_strUserAgent.c_str(),
  55. WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
  56. WINHTTP_NO_PROXY_NAME,
  57. WINHTTP_NO_PROXY_BYPASS,
  58. 0);
  59. if ( m_hSession == NULL ) {
  60. dwError = GetLastError();
  61. return false;
  62. }
  63. // 设置超时值;
  64. if ( !WinHttpSetTimeouts(m_hSession, item.m_nResolveTimeout, item.m_nConnectTimeout, item.m_nSendTimeout, item.m_nReceiveTimeout) ) {
  65. dwError = GetLastError();
  66. return false;
  67. }
  68. #pragma region 解析url;
  69. URL_COMPONENTS urlComp;
  70. DWORD dwUrlLen = 0;
  71. // 初始化URL_COMPONENTS结构体.
  72. ZeroMemory(&urlComp, sizeof(urlComp));
  73. urlComp.dwStructSize = sizeof(urlComp);
  74. // Set required component lengths to non-zero
  75. // so that they are cracked.
  76. urlComp.dwSchemeLength = (DWORD)-1;
  77. urlComp.dwHostNameLength = (DWORD)-1;
  78. urlComp.dwUrlPathLength = (DWORD)-1;
  79. urlComp.dwExtraInfoLength = (DWORD)-1;
  80. // Crack the URL.
  81. if (!WinHttpCrackUrl(item.m_strUrl.c_str(), item.m_strUrl.size(), 0, &urlComp)) {
  82. dwError = GetLastError();
  83. return false;
  84. }
  85. #pragma endregion
  86. // 连接服务器;
  87. m_hConnect = WinHttpConnect(m_hSession, urlComp.lpszHostName, urlComp.nPort, 0);
  88. if ( m_hConnect == NULL) {
  89. dwError = GetLastError();
  90. return false;
  91. }
  92. // 请求类型:是否是https;
  93. DWORD dwOpenRequestFlag = (urlComp.nScheme == INTERNET_SCHEME_HTTPS) ? WINHTTP_FLAG_SECURE : 0;
  94. m_hRequest = WinHttpOpenRequest(m_hConnect,
  95. item.m_strMethod.c_str(),
  96. urlComp.lpszUrlPath,NULL,
  97. WINHTTP_NO_REFERER,
  98. WINHTTP_DEFAULT_ACCEPT_TYPES,
  99. dwOpenRequestFlag);
  100. if ( m_hRequest == NULL ) {
  101. dwError = GetLastError();
  102. return false;
  103. }
  104. // 如果是https,那么客户端就很容易受到无效证书的影响,现在接受任何事情都是最容易的
  105. if ( item.m_brequireValidSSL && urlComp.nScheme == INTERNET_SCHEME_HTTPS ) {
  106. DWORD dwOps = SECURITY_FLAG_IGNORE_CERT_CN_INVALID
  107. | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID
  108. | SECURITY_FLAG_IGNORE_UNKNOWN_CA;
  109. WinHttpSetOption(m_hRequest, WINHTTP_OPTION_SECURITY_FLAGS, &dwOps, sizeof(DWORD));
  110. }
  111. bool bGetResponseSucceed=false;
  112. while ( !bGetResponseSucceed && m_nRetryTimes-- > 0 )
  113. {
  114. // 是否有请求头;
  115. if ( item.m_strHeader.size() > 0 )
  116. {
  117. if (!WinHttpAddRequestHeaders(m_hRequest, item.m_strHeader.c_str(), item.m_strHeader.size(), WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON))
  118. {
  119. continue;
  120. dwError = GetLastError();
  121. }
  122. }
  123. // 是否有Cookie;
  124. if ( item.m_strCookies.size() > 0 )
  125. {
  126. std::wstring cookies = L"Cookie: ";
  127. cookies += item.m_strCookies;
  128. if (!::WinHttpAddRequestHeaders(m_hRequest, cookies.c_str(), cookies.size(), WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON))
  129. {
  130. dwError = ::GetLastError();
  131. continue;
  132. }
  133. }
  134. // 是否有代理服务器;
  135. if ( item.m_strProxyServerList.size() > 0 )
  136. {
  137. WINHTTP_PROXY_INFO proxyInfo;
  138. memset(&proxyInfo, 0, sizeof(proxyInfo));
  139. proxyInfo.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
  140. wchar_t szProxy[MAX_PATH] = L"";
  141. wcscpy_s(szProxy, MAX_PATH, item.m_strProxyServerList.c_str());
  142. proxyInfo.lpszProxy = szProxy;
  143. if (!::WinHttpSetOption(m_hRequest, WINHTTP_OPTION_PROXY, &proxyInfo, sizeof(proxyInfo)))
  144. {
  145. dwError = ::GetLastError();
  146. continue;
  147. }
  148. if (item.m_strProxyUserName.size() > 0)
  149. {
  150. if (!::WinHttpSetOption(m_hRequest, WINHTTP_OPTION_PROXY_USERNAME, (LPVOID)item.m_strProxyUserName.c_str(), item.m_strProxyUserName.size() * sizeof(wchar_t)))
  151. {
  152. dwError = ::GetLastError();
  153. continue;
  154. }
  155. if (item.m_strProxyPwd.size() > 0)
  156. {
  157. if (!::WinHttpSetOption(m_hRequest, WINHTTP_OPTION_PROXY_PASSWORD, (LPVOID)item.m_strProxyPwd.c_str(), item.m_strProxyPwd.size() * sizeof(wchar_t)))
  158. {
  159. dwError = ::GetLastError();
  160. continue;
  161. }
  162. }
  163. }
  164. }
  165. // 是否关闭自动重定向;
  166. if ( !item.m_bAllowAutoRedirect )
  167. {
  168. DWORD dwDisableFeature = WINHTTP_DISABLE_REDIRECTS;
  169. if (!::WinHttpSetOption(m_hRequest, WINHTTP_OPTION_DISABLE_FEATURE, &dwDisableFeature, sizeof(dwDisableFeature)))
  170. {
  171. dwError = ::GetLastError();
  172. continue;
  173. }
  174. }
  175. // 发送请求;
  176. bool bSendRequestSucceed = false;
  177. if (::WinHttpSendRequest(m_hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, NULL))
  178. {
  179. bSendRequestSucceed = true;
  180. }
  181. else
  182. {
  183. // 从IE设置中查询代理信息,如果有代理,设置代理;
  184. WINHTTP_CURRENT_USER_IE_PROXY_CONFIG proxyConfig;
  185. memset(&proxyConfig, 0, sizeof(proxyConfig));
  186. if (::WinHttpGetIEProxyConfigForCurrentUser(&proxyConfig))
  187. {
  188. if (proxyConfig.lpszAutoConfigUrl != NULL)
  189. {
  190. WINHTTP_AUTOPROXY_OPTIONS autoProxyOptions;
  191. memset(&autoProxyOptions, 0, sizeof(autoProxyOptions));
  192. autoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT | WINHTTP_AUTOPROXY_CONFIG_URL;
  193. autoProxyOptions.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP;
  194. autoProxyOptions.lpszAutoConfigUrl = proxyConfig.lpszAutoConfigUrl;
  195. autoProxyOptions.fAutoLogonIfChallenged = TRUE;
  196. autoProxyOptions.dwReserved = 0;
  197. autoProxyOptions.lpvReserved = NULL;
  198. WINHTTP_PROXY_INFO proxyInfo;
  199. memset(&proxyInfo, 0, sizeof(proxyInfo));
  200. if (::WinHttpGetProxyForUrl(m_hSession, item.m_strUrl.c_str(), &autoProxyOptions, &proxyInfo))
  201. {
  202. if (::WinHttpSetOption(m_hRequest, WINHTTP_OPTION_PROXY, &proxyInfo, sizeof(proxyInfo)))
  203. {
  204. if (::WinHttpSendRequest(m_hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, NULL))
  205. {
  206. bSendRequestSucceed = true;
  207. }
  208. }
  209. if (proxyInfo.lpszProxy != NULL)
  210. {
  211. ::GlobalFree(proxyInfo.lpszProxy);
  212. }
  213. if (proxyInfo.lpszProxyBypass != NULL)
  214. {
  215. ::GlobalFree(proxyInfo.lpszProxyBypass);
  216. }
  217. }
  218. else
  219. {
  220. dwError = ::GetLastError();
  221. }
  222. }
  223. else if (proxyConfig.lpszProxy != NULL)
  224. {
  225. WINHTTP_PROXY_INFO proxyInfo;
  226. memset(&proxyInfo, 0, sizeof(proxyInfo));
  227. proxyInfo.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
  228. wchar_t szProxy[MAX_PATH] = L"";
  229. wcscpy_s(szProxy, MAX_PATH, proxyConfig.lpszProxy);
  230. proxyInfo.lpszProxy = szProxy;
  231. if (proxyConfig.lpszProxyBypass != NULL)
  232. {
  233. wchar_t szProxyBypass[MAX_PATH] = L"";
  234. wcscpy_s(szProxyBypass, MAX_PATH, proxyConfig.lpszProxyBypass);
  235. proxyInfo.lpszProxyBypass = szProxyBypass;
  236. }
  237. if (!::WinHttpSetOption(m_hRequest, WINHTTP_OPTION_PROXY, &proxyInfo, sizeof(proxyInfo)))
  238. {
  239. dwError = ::GetLastError();
  240. }
  241. }
  242. if (proxyConfig.lpszAutoConfigUrl != NULL)
  243. {
  244. ::GlobalFree(proxyConfig.lpszAutoConfigUrl);
  245. }
  246. if (proxyConfig.lpszProxy != NULL)
  247. {
  248. ::GlobalFree(proxyConfig.lpszProxy);
  249. }
  250. if (proxyConfig.lpszProxyBypass != NULL)
  251. {
  252. ::GlobalFree(proxyConfig.lpszProxyBypass);
  253. }
  254. }
  255. else
  256. {
  257. dwError = ::GetLastError();
  258. }
  259. }
  260. if (bSendRequestSucceed)
  261. {
  262. // 有要上传的数据;
  263. /*if (m_pDataToSend != NULL)
  264. {
  265. DWORD dwWritten = 0;
  266. if (!::WinHttpWriteData(m_hRequest,
  267. m_pDataToSend,
  268. m_dataToSendSize,
  269. &dwWritten))
  270. {
  271. dwError = ::GetLastError();
  272. }
  273. }*/
  274. if (::WinHttpReceiveResponse(m_hRequest, NULL))
  275. {
  276. DWORD dwSize = 0;
  277. BOOL bResult = FALSE;
  278. // 获取返回头;
  279. bResult = ::WinHttpQueryHeaders(m_hRequest,
  280. WINHTTP_QUERY_RAW_HEADERS_CRLF,
  281. WINHTTP_HEADER_NAME_BY_INDEX,
  282. NULL,
  283. &dwSize,
  284. WINHTTP_NO_HEADER_INDEX);
  285. if (bResult || (!bResult && (::GetLastError() == ERROR_INSUFFICIENT_BUFFER)))
  286. {
  287. wchar_t *szHeader = new wchar_t[dwSize];
  288. if (szHeader != NULL)
  289. {
  290. memset(szHeader, 0, dwSize* sizeof(wchar_t));
  291. if (::WinHttpQueryHeaders(m_hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX, szHeader, &dwSize, WINHTTP_NO_HEADER_INDEX))
  292. {
  293. httpResult.m_strHeader.assign(szHeader);
  294. std::vector<std::wstring> result;
  295. std::wstring regExp = L"";
  296. /*
  297. if (!m_bForceCharset)
  298. {
  299. regExp = L"charset={[A-Za-z0-9\\-_]+}";
  300. if (ParseRegExp(regExp, false, 1, m_responseHeader, result) && result.size() > 0)
  301. {
  302. httpResult.Charset = result[0];
  303. }
  304. }
  305. regExp = L"Content-Length: {[0-9]+}";
  306. if (ParseRegExp(regExp, false, 1, m_responseHeader, result) && result.size() > 0)
  307. {
  308. httpResult.dwByteCount = (unsigned int)_wtoi(result[0].c_str());
  309. }
  310. regExp = L"Location: {[0-9]+}";
  311. if (ParseRegExp(regExp, false, 1, m_responseHeader, result) && result.size() > 0)
  312. {
  313. httpResult.Location = result[0];
  314. }
  315. regExp = L"Set-Cookie:\\b*{.+?}\\n";
  316. if (ParseRegExp(regExp, false, 1, m_responseHeader, result) && result.size() > 0)
  317. {
  318. for (vector<wstring>::size_type i = 0; i < result.size(); i++)
  319. {
  320. httpResult.Cookie += result[i];
  321. if (i != result.size() - 1)
  322. {
  323. httpResult.Cookie += L"; ";
  324. }
  325. }
  326. httpResult.Cookie = Trim(httpResult.Cookie, L" ");
  327. if (httpResult.Cookie.size() > 0 && httpResult.Cookie[httpResult.Cookie.size() - 1] != L';')
  328. {
  329. httpResult.Cookie += L";";
  330. }
  331. }*/
  332. }
  333. delete[] szHeader;
  334. }
  335. }
  336. dwSize = 0;
  337. bResult = ::WinHttpQueryHeaders(m_hRequest,
  338. WINHTTP_QUERY_STATUS_CODE,
  339. WINHTTP_HEADER_NAME_BY_INDEX,
  340. NULL,
  341. &dwSize,
  342. WINHTTP_NO_HEADER_INDEX);
  343. if (bResult || (!bResult && (::GetLastError() == ERROR_INSUFFICIENT_BUFFER)))
  344. {
  345. wchar_t *szStatusCode = new wchar_t[dwSize];
  346. if (szStatusCode != NULL)
  347. {
  348. memset(szStatusCode, 0, dwSize* sizeof(wchar_t));
  349. if (::WinHttpQueryHeaders(m_hRequest,
  350. WINHTTP_QUERY_STATUS_CODE,
  351. WINHTTP_HEADER_NAME_BY_INDEX,
  352. szStatusCode,
  353. &dwSize,
  354. WINHTTP_NO_HEADER_INDEX))
  355. {
  356. httpResult.m_dwStatusCode = _wtol(szStatusCode);
  357. }
  358. delete[] szStatusCode;
  359. }
  360. }
  361. unsigned int iMaxBufferSize = 8912;
  362. unsigned int iCurrentBufferSize = 0;
  363. if (httpResult.m_pResponseData != NULL)
  364. {
  365. delete[] httpResult.m_pResponseData;
  366. httpResult.m_pResponseData = NULL;
  367. }
  368. httpResult.m_pResponseData = new BYTE[iMaxBufferSize];
  369. if (httpResult.m_pResponseData == NULL)
  370. {
  371. //bRetVal = false;
  372. break;
  373. }
  374. memset(httpResult.m_pResponseData, 0, iMaxBufferSize);
  375. do
  376. {
  377. dwSize = 0;
  378. if (::WinHttpQueryDataAvailable(m_hRequest, &dwSize))
  379. {
  380. //SetProgress(iCurrentBufferSize);
  381. BYTE *pResponse = new BYTE[dwSize + 1];
  382. if (pResponse != NULL)
  383. {
  384. memset(pResponse, 0, (dwSize + 1)*sizeof(BYTE));
  385. DWORD dwRead = 0;
  386. if (::WinHttpReadData(m_hRequest, pResponse, dwSize, &dwRead))
  387. {
  388. if (dwRead + iCurrentBufferSize > iMaxBufferSize)
  389. {
  390. BYTE *pOldBuffer = httpResult.m_pResponseData;
  391. httpResult.m_pResponseData = new BYTE[iMaxBufferSize * 2];
  392. if (httpResult.m_pResponseData == NULL)
  393. {
  394. httpResult.m_pResponseData = pOldBuffer;
  395. //bRetVal = false;
  396. break;
  397. }
  398. iMaxBufferSize *= 2;
  399. memset(httpResult.m_pResponseData, 0, iMaxBufferSize);
  400. memcpy(httpResult.m_pResponseData, pOldBuffer, iCurrentBufferSize);
  401. delete[] pOldBuffer;
  402. }
  403. memcpy(httpResult.m_pResponseData + iCurrentBufferSize, pResponse, dwRead);
  404. iCurrentBufferSize += dwRead;
  405. }
  406. delete[] pResponse;
  407. }
  408. }
  409. else
  410. {
  411. dwError = ::GetLastError();
  412. }
  413. }
  414. while (dwSize > 0);
  415. //SetProgress(iCurrentBufferSize);
  416. httpResult.m_dwResponseSize = iCurrentBufferSize;
  417. /*
  418. UINT codePage = CP_ACP;
  419. DWORD dwFlag = MB_PRECOMPOSED;
  420. if (_wcsnicmp(m_responseCharset.c_str(), L"utf-8", 5) == 0)
  421. {
  422. codePage = CP_UTF8;
  423. dwFlag = 0;
  424. }
  425. int iLength = ::MultiByteToWideChar(codePage, dwFlag, (LPCSTR)m_pResponse, m_responseByteCountReceived + 1, NULL, 0);
  426. if (iLength <= 0)
  427. {
  428. // Use CP_ACP if UTF-8 fail
  429. codePage = CP_ACP;
  430. dwFlag = MB_PRECOMPOSED;
  431. iLength = ::MultiByteToWideChar(codePage, dwFlag, (LPCSTR)m_pResponse, m_responseByteCountReceived + 1, NULL, 0);
  432. }
  433. if (iLength > 0)
  434. {
  435. wchar_t *wideChar = new wchar_t[iLength];
  436. if (wideChar != NULL)
  437. {
  438. memset(wideChar, 0, iLength * sizeof(wchar_t));
  439. iLength = ::MultiByteToWideChar(codePage, dwFlag, (LPCSTR)m_pResponse, m_responseByteCountReceived + 1, wideChar, iLength);
  440. if (iLength > 0)
  441. {
  442. m_responseContent = wideChar;
  443. }
  444. delete[] wideChar;
  445. }
  446. }*/
  447. bGetResponseSucceed = true;
  448. /*
  449. // If the resposne html web page size is less than 200, retry.
  450. if (verb == L"GET" && !disableAutoRedirect)
  451. {
  452. wstring regExp = L"{<html>}";
  453. vector<wstring> result;
  454. if (ParseRegExp(regExp, false, 1, m_responseContent, result) && result.size() > 0)
  455. {
  456. regExp = L"{</html>}";
  457. if (!ParseRegExp(regExp, false, 1, m_responseContent, result) || result.size() <= 0)
  458. {
  459. m_dwLastError = ERROR_INVALID_DATA;
  460. bGetReponseSucceed = false;
  461. }
  462. }
  463. }*/
  464. }
  465. else
  466. {
  467. dwError = ::GetLastError();
  468. }
  469. }
  470. }
  471. }
  472. return true;
  473. }
  474. bool HTTPHelper::SetCer(HTTPITEM &item)
  475. {
  476. return true;
  477. }
  478. bool HTTPHelper::SetTimeout(int nResolveTimeout /* = 0 */, int nConnectTimeout /* = 30000 */, int nSendTimeout /* = 30000 */, int nReceiveTimeout /* = 30000 */)
  479. {
  480. if ( m_hSession == NULL )
  481. return false;
  482. BOOL bRet = WinHttpSetTimeouts(m_hSession, nResolveTimeout, nConnectTimeout, nSendTimeout, nReceiveTimeout);
  483. if ( !bRet )
  484. {
  485. DWORD dwError = GetLastError();
  486. }
  487. return bRet;
  488. }
  489. bool HTTPHelper::SetUserAgent(std::string strAgent/* = */)
  490. {
  491. return true;
  492. }