bool CHttpClient::HttpPost(const char *url, const void * postData, int nPostDataSize, CHttpClientResponse &resp, bool formflag) { bool retVal = 1; for(int i = 0; i < HTTP_MAX_RETRIES; i++) { if( (retVal = DoPostInternal(url, postData, nPostDataSize, resp, formflag)) == 0) { if (resp.GetBodyLength() == 0) { //logFile.Write(LOG_BASIC, "HTTP POST returned no data - trying again..."); } else if (i > 0) { //logFile.Write(LOG_BASIC, "HTTP POST finally succeeded"); } break; } #ifdef SCUT_WIN32 Sleep(1000); #elif SCUT_ANDROID usleep(1000); #else usleep(1000); #endif } if (resp.GetBodyLength() == 0) { //logFile.Write(LOG_BASIC, "HTTP POST returned no data - returning failure..."); //retVal = 1; } return retVal; }
vector<CHttpClientResponse*> GZipUnZipTcpStream(unsigned char* pszData, unsigned int nLen) { vector<CHttpClientResponse*> ret; int nPackSize = 0; int nDelta = 0;//目前读取的长度 while (nDelta + 4 < nLen) { //读取头长度 unsigned char chPackSizes[4] = {0}; memcpy(chPackSizes, pszData, 4); pszData += 4; nDelta += 4; //获取头长度 nPackSize = *((int*)&chPackSizes[0]); if (nLen - nDelta < nPackSize) { break;; } unsigned char* pszBuffer = new unsigned char[nPackSize]; memset(pszBuffer, 0, nPackSize); memcpy(pszBuffer, pszData, nPackSize); pszData += nPackSize; nDelta += nPackSize; int nLen = 0; unsigned char* pszOut = NULL; if (pszBuffer[0] == 0x1f && pszBuffer[1] == 0x8b && pszBuffer[2] == 0x08 && pszBuffer[3] == 0x00) { unsigned char* pszOut; int nLen = ZipUtils::ccInflateMemory((unsigned char*)pszBuffer, nPackSize, (unsigned char**)&pszOut); if (nLen > 0) { CHttpClientResponse* pResp = new CHttpClientResponse(); CMemoryStream* pMem = new CMemoryStream(); pResp->SetTarget(pMem); pMem->WriteBuffer((char*)pszOut, nLen); ret.push_back(pResp); delete []pszOut; } } else { CHttpClientResponse* pResp = new CHttpClientResponse(); CMemoryStream* pMem = new CMemoryStream(); pResp->SetTarget(pMem); pMem->WriteBuffer((char*)pszBuffer, nPackSize); ret.push_back(pResp); } delete []pszBuffer; } return ret; }
bool ScutDataLogic::CDataRequest::ExecTcpRequest(CDataHandler* pHandler, const char* lpszUrl, const char* lpSendData, unsigned int nDataLen) { if (pHandler) { if (m_pTcpClient == NULL) { m_pTcpClient = new CTcpClient(); } if (nDataLen == 0) { nDataLen = strlen(lpSendData); } CHttpClientResponse resp; resp.SetTarget(new CMemoryStream()); resp.SetSendData(lpSendData, nDataLen); if (!m_pTcpClient->IsBusy()) { //直接执行同步请求 if (m_pTcpClient->TcpGet(lpszUrl, resp) == 0) //成功 { //在此判断是否存在 if (pHandler && pHandler->IsAlive()) { return pHandler->HandleData(0, *resp.GetTarget(), NULL); } } } else { CTcpClient* pTcpClient = new CTcpClient(); if (pTcpClient) { //直接执行同步请求 if (pTcpClient->TcpGet(lpszUrl, resp) == 0) //成功 { //在此判断是否存在 if (pHandler && pHandler->IsAlive()) { return pHandler->HandleData(0, *resp.GetTarget(), NULL); } } } } } return false; }
//写响应数据 static size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data) { register int realsize = size * nmemb; CHttpClientResponse* pResponse = (CHttpClientResponse*)data; if (pResponse->GetTarget()) { CStream* pStm = pResponse->GetTarget(); if (!pStm->WriteBuffer((char*)ptr, realsize)) { return 0; } } return realsize; }
/******************************************************************* * Function : DoGet() * Parameters: url - The URL to which an HTTP GET is to be done * resp - The response object which will store the HTTP * response received from the website * Returns : 0 - GET succeeded (could have any HTTP errors, * including 404 errors) * 1 - The GET failed most likely because a * connection coul not be established * Purpose : To do an HTTP GET with a max of HTTP_MAX_RETRIES retries *******************************************************************/ int CHttpClient::HttpGet(const char *url, CHttpClientResponse &resp) { int nRet = 1; for(int i = 0; i < HTTP_MAX_RETRIES; i++) { if ((nRet = DoGetInternal(url, resp)) == 0) { if (resp.GetBodyLength() == 0) { //logFile.Write(LOG_BASIC, "HTTP GET returned no data - trying again..."); } else if (i > 0) { //logFile.Write(LOG_BASIC, "HTTP GET finally succeeded"); } break; } FullReset(); #ifdef SCUT_WIN32 Sleep(1000); #elif SCUT_ANDROID usleep(1000); #else usleep(1000); #endif } return nRet; }
bool ScutDataLogic::CDataRequest::ExecRequest( CDataHandler* pHandler, const char* lpszUrl ) { if (pHandler) { CHttpSession hs; CHttpClient hc(&hs); CHttpClientResponse resp; resp.SetTarget(new CMemoryStream()); //直接执行同步请求 if (hc.HttpGet(lpszUrl, resp) == 0) //成功 { //在此判断是否存在 if (pHandler && pHandler->IsAlive()) { return pHandler->HandleData(0, *resp.GetTarget(), NULL); } } } return false; }
bool ScutDataLogic::CDataRequest::ExecRequest(void* pScene) { const std::string strPostData = CNetWriter::getInstance()->generatePostData(); if (strPostData.size()) { CHttpSession hs; CHttpClient hc(&hs); CHttpClientResponse resp; resp.SetTarget(new CMemoryStream()); //直接执行同步请求 int nRet = hc.HttpGet(strPostData.c_str(), resp); //处理LUA数据 CNetWriter::getInstance()->resetData(); if (nRet == 0) { LuaHandleData(pScene, 0, aisSucceed, resp.GetTarget(), NULL); } else { LuaHandleData(pScene, 0, 0, resp.GetTarget(), NULL); } } return false; }
/******************************************************************* * Function : DoGetInternal() * Parameters: url - The URL to which an HTTP GET is to be done * resp - The response object which will store the HTTP * response received from the website * Returns : TRUE - GET succeeded (could have any HTTP errors, * including 404 errors) * FALSE - The GET failed most likely because a * connection coul not be established * Purpose : To do an HTTP GET *******************************************************************/ int CHttpClient::DoGetInternal(const char *url, CHttpClientResponse &resp) { //m_bIsBusy = true; CURLcode res; MemoryStruct chunk; CScutString strProxy; CScutString strProxyAuth; chunk.memory = NULL; chunk.size = 0; chunk.session = session; chunk.headers.clear(); if (curl_handle == NULL) Initialize(); resp.SetRequestUrl(url); CScutString cookies = session->GetCookies(this); if (cookies != "") { //logFile.Write(LOG_COOKIE, "Setting curl cookie to: %s", LPCTSTR(cookies.c_str())); curl_easy_setopt(curl_handle, CURLOPT_COOKIE, LPCTSTR(cookies.c_str())); } curl_easy_setopt(curl_handle, CURLOPT_URL, url); curl_easy_setopt(curl_handle, CURLOPT_FILE, static_cast<void *>(&resp)); curl_easy_setopt(curl_handle, CURLOPT_WRITEHEADER, static_cast<void *>(&chunk)); curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers); //Ignore the Content-Length header. This is useful for Apache 1.x (and similar servers) which will report incorrect content length for files over 2 gigabytes. If this option is used, curl will not be able to accurately report progress, and will simply stop the download when the server ends the connection. //curl_easy_setopt(curl_handle, CURLOPT_IGNORE_CONTENT_LENGTH, TRUE); curl_easy_setopt(curl_handle, CURLOPT_HTTPGET, 1); //安全和代理服务器设置 if (settings.m_bProxyNTLM) curl_easy_setopt(curl_handle, CURLOPT_HTTPAUTH, CURLAUTH_NTLM); if (settings.m_bProxyAuthNTLM) curl_easy_setopt(curl_handle, CURLOPT_PROXYAUTH, CURLAUTH_NTLM); //超时时间 if (m_nTimeOut > 0) { curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, m_nTimeOut); } //断点续传 if (resp.GetUseDataResume() && resp.GetTarget()->GetSize() > 0) { //curl_easy_setopt(curl_handle, CURLOPT_RESUME_FROM_LARGE, resp.GetTarget()->GetSize()); CScutString strTemp; strTemp.Format("%d-", resp.GetTarget()->GetSize()); curl_easy_setopt(curl_handle, CURLOPT_RANGE, strTemp.c_str()); } if(CScutString::NoCaseCmp(url, "https://", 8) == 0) { if(bUseHttpsProxy) { strProxy.Format("%s:%d", httpsProxyHost, httpsProxyPort); curl_easy_setopt(curl_handle, CURLOPT_PROXY, strProxy.c_str()); } } else if(bUseHttpProxy) { strProxy.Format("%s:%d", httpProxyHost, httpProxyPort); curl_easy_setopt(curl_handle, CURLOPT_PROXY, strProxy.c_str()); } if(settings.m_bProxyAuth == TRUE) { strProxyAuth.Format("%s:%s", settings.m_strProxyAuthUsername.c_str(), settings.m_strProxyAuthPassword.c_str()); curl_easy_setopt(curl_handle, CURLOPT_PROXYUSERPWD, strProxyAuth.c_str()); } //进度设置,异步才启用进度显示功能 if (m_bUseProgressReport && m_bAsyncProcessing) { curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 0); curl_easy_setopt(curl_handle, CURLOPT_PROGRESSFUNCTION, ProgressReportProc); curl_easy_setopt(curl_handle, CURLOPT_PROGRESSDATA, this); } res = curl_easy_perform(curl_handle); char *effectiveUrl = NULL; curl_easy_getinfo(curl_handle, CURLINFO_EFFECTIVE_URL, &effectiveUrl); referer = effectiveUrl; //logFile.Write(LOG_ADVANCED, "last URL visited = %s", effectiveUrl); GetUrlHost(effectiveUrl, host); resp.SetLastResponseUrl(effectiveUrl); //获取状态码 int nStatus = 0; curl_easy_getinfo(curl_handle, CURLINFO_HTTP_CODE, &nStatus); resp.SetStatusCode(nStatus); char *conttype = NULL; curl_easy_getinfo(curl_handle, CURLINFO_CONTENT_TYPE, &conttype); //logFile.Write(LOG_ADVANCED, "Content-Type = %s", nvl(conttype,"(null)")); //resp.SetData(chunk.memory, chunk.size); resp.SetContentType(conttype); //处理压缩数据 if (IsGzipOrDeflateData(chunk) && resp.GetTarget()) { GZipUnZipStream(resp.GetTarget()); } /* if (res == CURLE_OK) { if (nStatus == 200) { //判断长度是否正确 double dContentLength = 0; CURLcode code = curl_easy_getinfo(curl_handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD , &dContentLength); if (code == CURLE_OK) //判断长度并解压 { if (resp.GetTarget()) { if (resp.GetTarget()->GetSize() == (int)dContentLength) { //处理压缩数据 if (IsGzipOrDeflateData(chunk)) { GZipUnZipStream(resp.GetTarget()); } } else res = CURLE_RECV_ERROR; } } else //直接解压 { //处理压缩数据 if (IsGzipOrDeflateData(chunk) && resp.GetTarget()) { GZipUnZipStream(resp.GetTarget()); } } } else res = CURLE_RECV_ERROR; } */ free(chunk.memory); if(res == CURLE_PARTIAL_FILE) { //logFile.Write(LOG_BASIC, "WARNING: HTTP GET returned CURL error: %s (%d) - ignoring",curl_easy_strerror(res), res); } if(res != CURLE_OK) { const char* strerror = curl_easy_strerror(res); if (strerror != NULL) { //m_pLogFile->Write(LOG_BASIC, strerror); } //logFile.Write(LOG_BASIC, "HTTP GET failed. CURL error: %s (%d)",curl_easy_strerror(res), res); } //m_bIsBusy = false; return res; }
int CHttpClient::DoPostInternal(const char *url, const void * postData, int nPostDataSize, CHttpClientResponse &resp, bool formflag) { //m_bIsBusy = true; CURLcode res; MemoryStruct chunk; CScutString strProxy; CScutString strProxyAuth; chunk.memory = NULL; /* we expect realloc(NULL, size) to work */ chunk.size = 0; /* no data at this point */ chunk.session = session; chunk.headers.clear(); /* init the curl session if necessary */ if (curl_handle == NULL) Initialize(); resp.SetRequestUrl(url); CScutString cookies = session->GetCookies(this); if (cookies != "") { //logFile.Write(LOG_COOKIE, "Setting curl cookie to: %s", LPCTSTR(cookies.c_str())); curl_easy_setopt(curl_handle, CURLOPT_COOKIE, LPCTSTR(cookies.c_str())); } /* specify URL to get */ curl_easy_setopt(curl_handle, CURLOPT_URL, url); /* send all data to this function */ //curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); curl_easy_setopt(curl_handle, CURLOPT_FILE, static_cast<void *>(&resp)); curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, HttpHeaderData); curl_easy_setopt(curl_handle, CURLOPT_WRITEHEADER, static_cast<void *>(&chunk)); curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers); //Apache服务器需要设定此项 //curl_easy_setopt(curl_handle, CURLOPT_IGNORE_CONTENT_LENGTH, TRUE); /* Set the operation to POST */ if (formflag) { curl_easy_setopt(curl_handle, CURLOPT_HTTPPOST, postData); } else { curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, postData); if (nPostDataSize != -1) { curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDSIZE, nPostDataSize); } } /* set proxy stuff */ if (settings.m_bProxyNTLM) curl_easy_setopt(curl_handle, CURLOPT_HTTPAUTH, CURLAUTH_NTLM); if (settings.m_bProxyAuthNTLM) curl_easy_setopt(curl_handle, CURLOPT_PROXYAUTH, CURLAUTH_NTLM); //超时处理 if (m_nTimeOut > 0) { curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, m_nTimeOut); } if(CScutString::NoCaseCmp(url, "https://", 8) == 0) { if(bUseHttpsProxy) { strProxy.Format("%s:%d", httpsProxyHost, httpsProxyPort); curl_easy_setopt(curl_handle, CURLOPT_PROXY, strProxy.c_str()); } } else if(bUseHttpProxy) { strProxy.Format("%s:%d", httpProxyHost, httpProxyPort); curl_easy_setopt(curl_handle, CURLOPT_PROXY, strProxy.c_str()); } if(settings.m_bProxyAuth == TRUE) { strProxyAuth.Format("%s:%s", settings.m_strProxyAuthUsername.c_str(), settings.m_strProxyAuthPassword.c_str()); curl_easy_setopt(curl_handle, CURLOPT_PROXYUSERPWD, strProxyAuth.c_str()); } /* get it! */ res = curl_easy_perform(curl_handle); char *effectiveUrl = NULL; curl_easy_getinfo(curl_handle, CURLINFO_EFFECTIVE_URL, &effectiveUrl); referer = effectiveUrl; //logFile.Write(LOG_ADVANCED, "last URL visited = %s", effectiveUrl); GetUrlHost(effectiveUrl, host); resp.SetLastResponseUrl(effectiveUrl); /* cleanup curl stuff */ /*curl_easy_cleanup(curl_handle); curl_handle = NULL;*/ //resp.SetData(chunk.memory, chunk.size); //处理压缩数据 if (IsGzipOrDeflateData(chunk) && resp.GetTarget()) { GZipUnZipStream(resp.GetTarget()); } free(chunk.memory); if(res == CURLE_PARTIAL_FILE) { //logFile.Write(LOG_BASIC, "WARNING: HTTP POST returned CURL error: %s (%d) - ignoring",curl_easy_strerror(res), res); } if(res != CURLE_OK) { //logFile.Write(LOG_BASIC, "HTTP POST failed. CURL error: %s (%d)",curl_easy_strerror(res), res); } //m_bIsBusy = false; return res; }