功能齐全的 Windows HTTP 包装器(C++)
一个功能齐全且易于使用的 C++ Windows HTTP 包装器。
引言
这是一个全功能的 Windows HTTP 封装器,使用 C++ 开发。它是一个 C++ 类的封装器,功能齐全且易于使用。您只需要包含一个头文件即可使用该封装器。
背景
几个月前,我在 CodeProject 上发表了第一篇文章 一个简单的 Windows HTTP 封装器,使用 C++ 开发。在过去的几个月里,我不断更新它,最终得到了基于 C++ 中 WinHTTP
API 的全功能 Windows HTTP 封装器。
特点
- 支持 Cookie
- 支持代理
- 支持
GET
和POST
方法 - 支持自定义请求头
- 支持禁用自动重定向
- 支持 HTTPS
- 支持接收进度
- 其他一些特性
Using the Code
类图如下:

您可以从函数名称中理解大多数函数的功能。请参考示例部分了解一些典型示例。
示例
简单的 Get 请求
Get 请求是最常见的请求。浏览网页会导致一个或多个 Get 请求。
// Set URL.
WinHttpClient client(L"https://codeproject.org.cn/");
// Send HTTP request, a GET request by default.
client.SendHttpRequest();
// The response header.
wstring httpResponseHeader = client.GetResponseHeader();
// The response content.
wstring httpResponseContent = client.GetResponseContent();
简单的 Post 请求
Post 请求通常发生在登录或发布帖子时。
WinHttpClient client(L"https://codeproject.org.cn/");
// Set post data.
string data = "title=A_NEW_THREAD&content=This_is_a_new_thread.";
client.SetAdditionalDataToSend((BYTE *)data.c_str(), data.size());
// Set request headers.
wchar_t szSize[50] = L"";
swprintf_s(szSize, L"%d", data.size());
wstring headers = L"Content-Length: ";
headers += szSize;
headers += L"\r\nContent-Type: application/x-www-form-urlencoded\r\n";
client.SetAdditionalRequestHeaders(headers);
// Send HTTP post request.
client.SendHttpRequest(L"POST");
wstring httpResponseHeader = client.GetResponseHeader();
wstring httpResponseContent = client.GetResponseContent();
获取请求的进度
您可以指定一个回调函数来获取请求的进度。
// Progress - finished percentage.
bool ProgressProc(double progress)
{
wprintf(L"Current progress: %-.1f%%\r\n", progress);
return true;
}
void ProgressTest(void)
{
// Set URL and call back function.
WinHttpClient client(L"https://codeproject.org.cn/", ProgressProc);
client.SendHttpRequest();
wstring httpResponseHeader = client.GetResponseHeader();
wstring httpResponseContent = client.GetResponseContent();
}
指定用户代理
用户代理是一个 string
,客户端使用它来向 Web 服务器标识自己,以便服务器可以知道您使用的客户端软件,例如 Internet Explorer 8、Chrome 或 FireFox。您可以指定用户代理来伪装成 Internet Explorer 8,从而欺骗 Web 服务器,因为有时服务器仅支持 Internet Explorer 8。
WinHttpClient client(L"https://codeproject.org.cn/");
// Set the user agent to the same as Internet Explorer 8.
client.SetUserAgent(L"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1;...)");
client.SendHttpRequest();
wstring httpResponseHeader = client.GetResponseHeader();
wstring httpResponseContent = client.GetResponseContent();
指定代理
有时,我们必须通过代理连接到 Web。默认情况下,WinHttpClient
直接连接到 Web 服务器,如果连接失败,则使用 Internet Explorer 设置进行连接。您也可以通过调用函数 SetProxy
来指定代理。
WinHttpClient client(L"https://codeproject.org.cn/");
// Set the proxy to 192.168.0.1 with port 8080.
client.SetProxy(L"192.168.0.1:8080");
client.SendHttpRequest();
wstring httpResponseHeader = client.GetResponseHeader();
wstring httpResponseContent = client.GetResponseContent();
处理 Cookies
Cookie(也称为跟踪 Cookie、浏览器 Cookie 和 HTTP Cookie)是由 Web 浏览器存储在用户计算机上的一个小文本片段。Cookie 由包含信息位的一个或多个名称-值对组成。
Cookie 由 Web 服务器作为 HTTP 标头发送到 Web 浏览器,然后每次浏览器访问该服务器时,都会将 Cookie 不变地发送回服务器。Cookie 可用于身份验证、会话跟踪(状态维护)、存储站点首选项、购物车内容、基于服务器的会话的标识符,或可以通过存储文本数据实现的任何其他操作 (http://en.wikipedia.org/wiki/HTTP_cookie)。
您可以通过调用 SetAdditionalRequestCookies
来指定要发送的 Cookie,并通过调用 GetResponseCookies
来获取响应 Cookie。
WinHttpClient client(L"https://codeproject.org.cn/");
// Set the cookies to send.
client.SetAdditionalRequestCookies(L"username=jack");
client.SendHttpRequest();
// Get the response cookies.
wstring httpResponseCookies = client.GetResponseCookies();
wstring httpResponseHeader = client.GetResponseHeader();
wstring httpResponseContent = client.GetResponseContent();
HTTPS
WinHttpClient client(L"https://www.google.com/");
// Accept any certificate while performing HTTPS request.
client.RequireValidSslCertificates(false);
client.SendHttpRequest();
wstring httpResponseHeader = client.GetResponseHeader();
wstring httpResponseContent = client.GetResponseContent();
多个请求
WinHttpClient client(L"http://www.google.com/");
client.SendHttpRequest();
wstring httpResponseHeader = client.GetResponseHeader();
wstring httpResponseContent = client.GetResponseContent();
// Update the URL.
client.UpdateUrl(L"http://www.microsoft.com/");
client.SendHttpRequest();
httpResponseHeader = client.GetResponseHeader();
httpResponseContent = client.GetResponseContent();
一个完整的示例
Codeproject.com 需要登录才能下载文件。此示例登录,获取 Cookie,请求我的第一篇 CodeProject 文章 一个简单的 Windows HTTP 封装器,使用 C++ 开发 的源代码 (win_HTTP_wrapper/WinHttpClient_Src.zip),然后将文件保存到硬盘。此示例包括 Cookie 处理、Post 请求、请求头自定义等。
// 1. Get the initial cookie.
WinHttpClient getClient
(L"https://codeproject.org.cn/script/Membership/LogOn.aspx");
getClient.SetAdditionalRequestHeaders
(L"Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, ...");
if (!getClient.SendHttpRequest())
{
return;
}
// 2. Post data to get the authentication cookie.
WinHttpClient postClient
(L"https://codeproject.org.cn/script/Membership/LogOn.aspx?rp=
%2fscript%2fMembership%2fLogOn.aspx");
// Post data.
wstring username = L"YourCodeProjectUsername";
wstring password = L"YourPassword";
postClient.SetAdditionalRequestCookies(getClient.GetResponseCookies());
string data = "FormName=MenuBarForm&Email=";
data += (char *)_bstr_t(username.c_str());
data += "&Password=";
data += (char *)_bstr_t(password.c_str());
data += "&RememberMeCheck=1";
postClient.SetAdditionalDataToSend((BYTE *)data.c_str(), data.size());
// Post headers.
wstring headers = L"...Content-Length: %d\r\nProxy-Connection:
Keep-Alive\r\nPragma: no-cache\r\n";
wchar_t szHeaders[MAX_PATH * 10] = L"";
swprintf_s(szHeaders, MAX_PATH * 10, headers.c_str(), data.size());
postClient.SetAdditionalRequestHeaders(szHeaders);
if (!postClient.SendHttpRequest(L"POST", true))
{
return;
}
// 3. Finally get the zip file.
WinHttpClient downloadClient(L"win_HTTP_wrapper/WinHttpClient_Src.zip");
downloadClient.SetUserAgent(L"Mozilla/4.0
(compatible; MSIE 8.0; Windows NT 5.1; ...)");
// Sending this cookie makes the server believe you have already logged in.
downloadClient.SetAdditionalRequestCookies(postClient.GetResponseCookies());
if (!downloadClient.SendHttpRequest())
{
return;
}
downloadClient.SaveResponseToFile(L"C:\\WinHttpClient_Src.zip");
关注点
- 有时,先让一段新代码运行起来,然后再改进它,是个好主意。
- 阅读超文本传输协议 (RFC 2616) 将有很大帮助。
- 使用 HTTP 监控工具来帮助开发,例如
HTTPAnalyzer
或HTTPWatch
。 - 使用类
_bstr_t
在wchar_t*
和char*
之间进行转换非常快速且容易。
历史
- 2010-9-21 2 项增强功能,感谢 Scott Leckie
- 2010-4-29 修复了 2 个错误,感谢 Wong Shao Voon
- 2009-9 全功能版本
- 2008-7 初始版本