代码中使用TCHAR当参数是为了方便支持unicode和ansi,使用string当返回值是因为web返回的一般都是utf8字符,所以最好在加一个utf82gbk接口转换,可能还要加s2cs转cstring或者unicode。
CommonLog是我自己的接口,可以忽略
#include <WinInet.h>
#pragma comment(lib, "Wininet.lib")
string HttpRequest(const TCHAR * lpHostName, const TCHAR * lpUrl, const TCHAR * lpMethod, short sPort=80, char * lpPostData=NULL, int nPostDataLen=0);
string HttpRequest(const TCHAR * lpHostName, const TCHAR * lpUrl, const TCHAR * lpMethod, short sPort, char * lpPostData, int nPostDataLen)
{
HINTERNET hInternet = NULL, hConnect = NULL, hRequest = NULL;
TCHAR headerContentType[] = _T("Content-Type:application/x-www-form-urlencoded");
TCHAR headAccept[] = _T("Accept: application/json, text/plain, */*");
DWORD dwLastError = 0;
BOOL bRet;
std::string strResponse;
hInternet = (HINSTANCE)InternetOpen(_T("User-Agent"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if (!hInternet)
{
CommonLog::getInstance()->WriteLog(LogLevel_debug, _T("InternetOpen user-agent failed"));
goto end;
}
//hostname可以写www.baidu.com,不能写http://www.baidu.com,
hConnect = (HINSTANCE)InternetConnect(hInternet, lpHostName, sPort, NULL, _T("HTTP/1.1"), INTERNET_SERVICE_HTTP, 0, 0);
if (!hConnect)
{
CommonLog::getInstance()->WriteLog(LogLevel_debug, _T("InternetConnect failed"));
goto end;
}
hRequest = (HINSTANCE)HttpOpenRequest(hConnect, lpMethod, lpUrl, _T("HTTP/1.1"), NULL, NULL, INTERNET_FLAG_RELOAD, 0);
if (!hRequest)
{
CommonLog::getInstance()->WriteLog(LogLevel_debug, _T("HttpOpenRequest failed"));
goto end;
}
///header可以加其他的///
//_tcslen(headerContentType)千万不要因为以前养成的好习惯而加上*sizeof(TCHAR),不然header中会有乱码,看起来是length表示的是utf-8的长度,不是占用的字节数
//nginx可能会报400
bRet = HttpAddRequestHeaders(hRequest, headerContentType,_tcslen(headerContentType),HTTP_ADDREQ_FLAG_REPLACE | HTTP_ADDREQ_FLAG_ADD);
if(!bRet)
{
CommonLog::getInstance()->WriteLog(LogLevel_debug, _T("HttpAddRequestHeaders failed"));
goto end;
}
bRet = HttpAddRequestHeaders(hRequest, headAccept,_tcslen(headAccept),HTTP_ADDREQ_FLAG_REPLACE | HTTP_ADDREQ_FLAG_ADD);
if(!bRet)
{
CommonLog::getInstance()->WriteLog(LogLevel_debug, _T("HttpAddRequestHeaders2 failed"));
goto end;
}
bRet = HttpSendRequest(hRequest, NULL, 0, lpPostData, nPostDataLen);
dwLastError = GetLastError();
// 1个小bug,不要再写日志的的地方把GetLastError()当参数,可能日志打开文件也会报错183(重复打开已经存在的文件)
while (TRUE)
{
char cReadBuffer[4096];
unsigned long lNumberOfBytesRead;
bRet = InternetReadFile(hRequest, cReadBuffer, sizeof(cReadBuffer) - 1, &lNumberOfBytesRead);
if (!bRet || !lNumberOfBytesRead)
{
break;
}
cReadBuffer[lNumberOfBytesRead] = 0;
strResponse = strResponse + cReadBuffer;
}
end:
if (hRequest)
InternetCloseHandle(hRequest);
if (hConnect)
InternetCloseHandle(hConnect);
if (hInternet)
InternetCloseHandle(hInternet);
return strResponse;
}
实例:
string res = HttpRequest(_T("www.test.com"), _T("/test/testReply"),
_T("get"));
错误:
hostname中加http会报错
GetLastError最好放在函数调用后的第一行代码,不要再函数和函数后面的GetLastError中加入自己的代码,哪怕自己的代码不主动报错,切记不要把GetLastError()当参数,