123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541 |
- #include "StdAfx.h"
- #include "HTTPHelper.h"
- HTTPHelper::HTTPHelper(void):m_hSession(NULL),m_hConnect(NULL),m_hRequest(NULL),m_nRetryTimes(3)
- {
- }
- HTTPHelper::~HTTPHelper(void)
- {
- }
- bool HTTPHelper::UrlParse(std::wstring strUrl)
- {
- int nPos = 0;
- m_strUrl = strUrl;
- std::wstring strSub;
- wchar_t* magic[] = { L"https://", L"http://", NULL };
- if ( m_strUrl.find(magic[0]) != std::wstring::npos || m_strUrl.find(magic[1]) != std::wstring::npos ) {
- if (m_strUrl.find(magic[0]) != std::wstring::npos) {
- m_dwPort = 443;
- m_brequireValidSSL=TRUE;
- strSub = m_strUrl.substr(8);
-
- } else {
- m_dwPort = 80;
- m_brequireValidSSL=FALSE;
- strSub = m_strUrl.substr(7);
- }
- if ( (nPos = strSub.find(L"/")) != std::wstring::npos ) {
- m_strDomain = strSub.substr(0, nPos);
- m_strParam = strSub.substr(nPos);
- } else {
- m_strDomain = strSub;
- m_strParam = L"/";
- }
- if ( (nPos = m_strDomain.find(L":")) != std::wstring::npos ) {
- m_strHost = m_strDomain.substr(0, nPos);
- m_dwPort = _wtol(m_strDomain.substr(nPos+1).c_str());
- } else {
- m_strHost = m_strDomain;
- }
- return TRUE;
- }
- return FALSE;
- }
- bool HTTPHelper::GetHtml(HTTPITEM &item, HTTPRESULT &result)
- {
- if ( !SendRequest(item,result) )
- return false;
- return true;
- }
- bool HTTPHelper::SendRequest(HTTPITEM &item,HTTPRESULT &httpResult)
- {
- DWORD dwError = -1;
- if ( m_hSession == NULL ) {
- // 创建会话;
- m_hSession = WinHttpOpen(
- item.m_strUserAgent.c_str(),
- WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
- WINHTTP_NO_PROXY_NAME,
- WINHTTP_NO_PROXY_BYPASS,
- 0);
- if ( m_hSession == NULL ) {
- dwError = GetLastError();
- return false;
- }
- // 设置超时值;
- if ( !WinHttpSetTimeouts(m_hSession, item.m_nResolveTimeout, item.m_nConnectTimeout, item.m_nSendTimeout, item.m_nReceiveTimeout) ) {
- dwError = GetLastError();
- return false;
- }
- #pragma region 解析url;
- URL_COMPONENTS urlComp;
- DWORD dwUrlLen = 0;
- // 初始化URL_COMPONENTS结构体.
- ZeroMemory(&urlComp, sizeof(urlComp));
- urlComp.dwStructSize = sizeof(urlComp);
- // Set required component lengths to non-zero
- // so that they are cracked.
- urlComp.dwSchemeLength = (DWORD)-1;
- urlComp.dwHostNameLength = (DWORD)-1;
- urlComp.dwUrlPathLength = (DWORD)-1;
- urlComp.dwExtraInfoLength = (DWORD)-1;
- // Crack the URL.
- if (!WinHttpCrackUrl(item.m_strUrl.c_str(), item.m_strUrl.size(), 0, &urlComp)) {
- dwError = GetLastError();
- return false;
- }
- #pragma endregion
- // 连接服务器;
- m_hConnect = WinHttpConnect(m_hSession, urlComp.lpszHostName, urlComp.nPort, 0);
- if ( m_hConnect == NULL) {
- dwError = GetLastError();
- return false;
- }
- // 请求类型:是否是https;
- DWORD dwOpenRequestFlag = (urlComp.nScheme == INTERNET_SCHEME_HTTPS) ? WINHTTP_FLAG_SECURE : 0;
- m_hRequest = WinHttpOpenRequest(m_hConnect,
- item.m_strMethod.c_str(),
- urlComp.lpszUrlPath,NULL,
- WINHTTP_NO_REFERER,
- WINHTTP_DEFAULT_ACCEPT_TYPES,
- dwOpenRequestFlag);
- if ( m_hRequest == NULL ) {
- dwError = GetLastError();
- return false;
- }
- // 如果是https,那么客户端就很容易受到无效证书的影响,现在接受任何事情都是最容易的
- if ( item.m_brequireValidSSL && urlComp.nScheme == INTERNET_SCHEME_HTTPS ) {
- DWORD dwOps = SECURITY_FLAG_IGNORE_CERT_CN_INVALID
- | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID
- | SECURITY_FLAG_IGNORE_UNKNOWN_CA;
- WinHttpSetOption(m_hRequest, WINHTTP_OPTION_SECURITY_FLAGS, &dwOps, sizeof(DWORD));
- }
- bool bGetResponseSucceed=false;
- while ( !bGetResponseSucceed && m_nRetryTimes-- > 0 )
- {
- // 是否有请求头;
- if ( item.m_strHeader.size() > 0 )
- {
- if (!WinHttpAddRequestHeaders(m_hRequest, item.m_strHeader.c_str(), item.m_strHeader.size(), WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON))
- {
- continue;
- dwError = GetLastError();
- }
- }
- // 是否有Cookie;
- if ( item.m_strCookies.size() > 0 )
- {
- std::wstring cookies = L"Cookie: ";
- cookies += item.m_strCookies;
- if (!::WinHttpAddRequestHeaders(m_hRequest, cookies.c_str(), cookies.size(), WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON))
- {
- dwError = ::GetLastError();
- continue;
- }
- }
- // 是否有代理服务器;
- if ( item.m_strProxyServerList.size() > 0 )
- {
- WINHTTP_PROXY_INFO proxyInfo;
- memset(&proxyInfo, 0, sizeof(proxyInfo));
- proxyInfo.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
- wchar_t szProxy[MAX_PATH] = L"";
- wcscpy_s(szProxy, MAX_PATH, item.m_strProxyServerList.c_str());
- proxyInfo.lpszProxy = szProxy;
- if (!::WinHttpSetOption(m_hRequest, WINHTTP_OPTION_PROXY, &proxyInfo, sizeof(proxyInfo)))
- {
- dwError = ::GetLastError();
- continue;
- }
- if (item.m_strProxyUserName.size() > 0)
- {
- if (!::WinHttpSetOption(m_hRequest, WINHTTP_OPTION_PROXY_USERNAME, (LPVOID)item.m_strProxyUserName.c_str(), item.m_strProxyUserName.size() * sizeof(wchar_t)))
- {
- dwError = ::GetLastError();
- continue;
- }
- if (item.m_strProxyPwd.size() > 0)
- {
- if (!::WinHttpSetOption(m_hRequest, WINHTTP_OPTION_PROXY_PASSWORD, (LPVOID)item.m_strProxyPwd.c_str(), item.m_strProxyPwd.size() * sizeof(wchar_t)))
- {
- dwError = ::GetLastError();
- continue;
- }
- }
- }
- }
- // 是否关闭自动重定向;
- if ( !item.m_bAllowAutoRedirect )
- {
- DWORD dwDisableFeature = WINHTTP_DISABLE_REDIRECTS;
- if (!::WinHttpSetOption(m_hRequest, WINHTTP_OPTION_DISABLE_FEATURE, &dwDisableFeature, sizeof(dwDisableFeature)))
- {
- dwError = ::GetLastError();
- continue;
- }
- }
- // 发送请求;
- bool bSendRequestSucceed = false;
- if (::WinHttpSendRequest(m_hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, NULL))
- {
- bSendRequestSucceed = true;
- }
- else
- {
- // 从IE设置中查询代理信息,如果有代理,设置代理;
- WINHTTP_CURRENT_USER_IE_PROXY_CONFIG proxyConfig;
- memset(&proxyConfig, 0, sizeof(proxyConfig));
- if (::WinHttpGetIEProxyConfigForCurrentUser(&proxyConfig))
- {
- if (proxyConfig.lpszAutoConfigUrl != NULL)
- {
- WINHTTP_AUTOPROXY_OPTIONS autoProxyOptions;
- memset(&autoProxyOptions, 0, sizeof(autoProxyOptions));
- autoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT | WINHTTP_AUTOPROXY_CONFIG_URL;
- autoProxyOptions.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP;
- autoProxyOptions.lpszAutoConfigUrl = proxyConfig.lpszAutoConfigUrl;
- autoProxyOptions.fAutoLogonIfChallenged = TRUE;
- autoProxyOptions.dwReserved = 0;
- autoProxyOptions.lpvReserved = NULL;
- WINHTTP_PROXY_INFO proxyInfo;
- memset(&proxyInfo, 0, sizeof(proxyInfo));
- if (::WinHttpGetProxyForUrl(m_hSession, item.m_strUrl.c_str(), &autoProxyOptions, &proxyInfo))
- {
- if (::WinHttpSetOption(m_hRequest, WINHTTP_OPTION_PROXY, &proxyInfo, sizeof(proxyInfo)))
- {
- if (::WinHttpSendRequest(m_hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, NULL))
- {
- bSendRequestSucceed = true;
- }
- }
- if (proxyInfo.lpszProxy != NULL)
- {
- ::GlobalFree(proxyInfo.lpszProxy);
- }
- if (proxyInfo.lpszProxyBypass != NULL)
- {
- ::GlobalFree(proxyInfo.lpszProxyBypass);
- }
- }
- else
- {
- dwError = ::GetLastError();
- }
- }
- else if (proxyConfig.lpszProxy != NULL)
- {
- WINHTTP_PROXY_INFO proxyInfo;
- memset(&proxyInfo, 0, sizeof(proxyInfo));
- proxyInfo.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
- wchar_t szProxy[MAX_PATH] = L"";
- wcscpy_s(szProxy, MAX_PATH, proxyConfig.lpszProxy);
- proxyInfo.lpszProxy = szProxy;
- if (proxyConfig.lpszProxyBypass != NULL)
- {
- wchar_t szProxyBypass[MAX_PATH] = L"";
- wcscpy_s(szProxyBypass, MAX_PATH, proxyConfig.lpszProxyBypass);
- proxyInfo.lpszProxyBypass = szProxyBypass;
- }
- if (!::WinHttpSetOption(m_hRequest, WINHTTP_OPTION_PROXY, &proxyInfo, sizeof(proxyInfo)))
- {
- dwError = ::GetLastError();
- }
- }
- if (proxyConfig.lpszAutoConfigUrl != NULL)
- {
- ::GlobalFree(proxyConfig.lpszAutoConfigUrl);
- }
- if (proxyConfig.lpszProxy != NULL)
- {
- ::GlobalFree(proxyConfig.lpszProxy);
- }
- if (proxyConfig.lpszProxyBypass != NULL)
- {
- ::GlobalFree(proxyConfig.lpszProxyBypass);
- }
- }
- else
- {
- dwError = ::GetLastError();
- }
- }
- if (bSendRequestSucceed)
- {
- // 有要上传的数据;
- /*if (m_pDataToSend != NULL)
- {
- DWORD dwWritten = 0;
- if (!::WinHttpWriteData(m_hRequest,
- m_pDataToSend,
- m_dataToSendSize,
- &dwWritten))
- {
- dwError = ::GetLastError();
- }
- }*/
- if (::WinHttpReceiveResponse(m_hRequest, NULL))
- {
- DWORD dwSize = 0;
- BOOL bResult = FALSE;
- // 获取返回头;
- bResult = ::WinHttpQueryHeaders(m_hRequest,
- WINHTTP_QUERY_RAW_HEADERS_CRLF,
- WINHTTP_HEADER_NAME_BY_INDEX,
- NULL,
- &dwSize,
- WINHTTP_NO_HEADER_INDEX);
- if (bResult || (!bResult && (::GetLastError() == ERROR_INSUFFICIENT_BUFFER)))
- {
- wchar_t *szHeader = new wchar_t[dwSize];
- if (szHeader != NULL)
- {
- memset(szHeader, 0, dwSize* sizeof(wchar_t));
- if (::WinHttpQueryHeaders(m_hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX, szHeader, &dwSize, WINHTTP_NO_HEADER_INDEX))
- {
- httpResult.m_strHeader.assign(szHeader);
- std::vector<std::wstring> result;
- std::wstring regExp = L"";
- /*
- if (!m_bForceCharset)
- {
- regExp = L"charset={[A-Za-z0-9\\-_]+}";
- if (ParseRegExp(regExp, false, 1, m_responseHeader, result) && result.size() > 0)
- {
- httpResult.Charset = result[0];
- }
- }
- regExp = L"Content-Length: {[0-9]+}";
- if (ParseRegExp(regExp, false, 1, m_responseHeader, result) && result.size() > 0)
- {
- httpResult.dwByteCount = (unsigned int)_wtoi(result[0].c_str());
- }
- regExp = L"Location: {[0-9]+}";
- if (ParseRegExp(regExp, false, 1, m_responseHeader, result) && result.size() > 0)
- {
- httpResult.Location = result[0];
- }
- regExp = L"Set-Cookie:\\b*{.+?}\\n";
- if (ParseRegExp(regExp, false, 1, m_responseHeader, result) && result.size() > 0)
- {
- for (vector<wstring>::size_type i = 0; i < result.size(); i++)
- {
- httpResult.Cookie += result[i];
- if (i != result.size() - 1)
- {
- httpResult.Cookie += L"; ";
- }
- }
- httpResult.Cookie = Trim(httpResult.Cookie, L" ");
- if (httpResult.Cookie.size() > 0 && httpResult.Cookie[httpResult.Cookie.size() - 1] != L';')
- {
- httpResult.Cookie += L";";
- }
- }*/
- }
- delete[] szHeader;
- }
- }
- dwSize = 0;
- bResult = ::WinHttpQueryHeaders(m_hRequest,
- WINHTTP_QUERY_STATUS_CODE,
- WINHTTP_HEADER_NAME_BY_INDEX,
- NULL,
- &dwSize,
- WINHTTP_NO_HEADER_INDEX);
- if (bResult || (!bResult && (::GetLastError() == ERROR_INSUFFICIENT_BUFFER)))
- {
- wchar_t *szStatusCode = new wchar_t[dwSize];
- if (szStatusCode != NULL)
- {
- memset(szStatusCode, 0, dwSize* sizeof(wchar_t));
- if (::WinHttpQueryHeaders(m_hRequest,
- WINHTTP_QUERY_STATUS_CODE,
- WINHTTP_HEADER_NAME_BY_INDEX,
- szStatusCode,
- &dwSize,
- WINHTTP_NO_HEADER_INDEX))
- {
- httpResult.m_dwStatusCode = _wtol(szStatusCode);
- }
- delete[] szStatusCode;
- }
- }
- unsigned int iMaxBufferSize = 8912;
- unsigned int iCurrentBufferSize = 0;
- if (httpResult.m_pResponseData != NULL)
- {
- delete[] httpResult.m_pResponseData;
- httpResult.m_pResponseData = NULL;
- }
- httpResult.m_pResponseData = new BYTE[iMaxBufferSize];
- if (httpResult.m_pResponseData == NULL)
- {
- //bRetVal = false;
- break;
- }
- memset(httpResult.m_pResponseData, 0, iMaxBufferSize);
- do
- {
- dwSize = 0;
- if (::WinHttpQueryDataAvailable(m_hRequest, &dwSize))
- {
- //SetProgress(iCurrentBufferSize);
- BYTE *pResponse = new BYTE[dwSize + 1];
- if (pResponse != NULL)
- {
- memset(pResponse, 0, (dwSize + 1)*sizeof(BYTE));
- DWORD dwRead = 0;
- if (::WinHttpReadData(m_hRequest, pResponse, dwSize, &dwRead))
- {
- if (dwRead + iCurrentBufferSize > iMaxBufferSize)
- {
- BYTE *pOldBuffer = httpResult.m_pResponseData;
- httpResult.m_pResponseData = new BYTE[iMaxBufferSize * 2];
- if (httpResult.m_pResponseData == NULL)
- {
- httpResult.m_pResponseData = pOldBuffer;
- //bRetVal = false;
- break;
- }
- iMaxBufferSize *= 2;
- memset(httpResult.m_pResponseData, 0, iMaxBufferSize);
- memcpy(httpResult.m_pResponseData, pOldBuffer, iCurrentBufferSize);
- delete[] pOldBuffer;
- }
- memcpy(httpResult.m_pResponseData + iCurrentBufferSize, pResponse, dwRead);
- iCurrentBufferSize += dwRead;
- }
- delete[] pResponse;
- }
- }
- else
- {
- dwError = ::GetLastError();
- }
- }
- while (dwSize > 0);
- //SetProgress(iCurrentBufferSize);
- httpResult.m_dwResponseSize = iCurrentBufferSize;
- /*
- UINT codePage = CP_ACP;
- DWORD dwFlag = MB_PRECOMPOSED;
- if (_wcsnicmp(m_responseCharset.c_str(), L"utf-8", 5) == 0)
- {
- codePage = CP_UTF8;
- dwFlag = 0;
- }
- int iLength = ::MultiByteToWideChar(codePage, dwFlag, (LPCSTR)m_pResponse, m_responseByteCountReceived + 1, NULL, 0);
- if (iLength <= 0)
- {
- // Use CP_ACP if UTF-8 fail
- codePage = CP_ACP;
- dwFlag = MB_PRECOMPOSED;
- iLength = ::MultiByteToWideChar(codePage, dwFlag, (LPCSTR)m_pResponse, m_responseByteCountReceived + 1, NULL, 0);
- }
- if (iLength > 0)
- {
- wchar_t *wideChar = new wchar_t[iLength];
- if (wideChar != NULL)
- {
- memset(wideChar, 0, iLength * sizeof(wchar_t));
- iLength = ::MultiByteToWideChar(codePage, dwFlag, (LPCSTR)m_pResponse, m_responseByteCountReceived + 1, wideChar, iLength);
- if (iLength > 0)
- {
- m_responseContent = wideChar;
- }
- delete[] wideChar;
- }
- }*/
- bGetResponseSucceed = true;
- /*
- // If the resposne html web page size is less than 200, retry.
- if (verb == L"GET" && !disableAutoRedirect)
- {
- wstring regExp = L"{<html>}";
- vector<wstring> result;
- if (ParseRegExp(regExp, false, 1, m_responseContent, result) && result.size() > 0)
- {
- regExp = L"{</html>}";
- if (!ParseRegExp(regExp, false, 1, m_responseContent, result) || result.size() <= 0)
- {
- m_dwLastError = ERROR_INVALID_DATA;
- bGetReponseSucceed = false;
- }
- }
- }*/
- }
- else
- {
- dwError = ::GetLastError();
- }
- }
- }
- }
- return true;
- }
- bool HTTPHelper::SetCer(HTTPITEM &item)
- {
- return true;
- }
- bool HTTPHelper::SetTimeout(int nResolveTimeout /* = 0 */, int nConnectTimeout /* = 30000 */, int nSendTimeout /* = 30000 */, int nReceiveTimeout /* = 30000 */)
- {
- if ( m_hSession == NULL )
- return false;
- BOOL bRet = WinHttpSetTimeouts(m_hSession, nResolveTimeout, nConnectTimeout, nSendTimeout, nReceiveTimeout);
- if ( !bRet )
- {
- DWORD dwError = GetLastError();
- }
- return bRet;
- }
- bool HTTPHelper::SetUserAgent(std::string strAgent/* = */)
- {
- return true;
- }
|