#include <windows.h>
#include <iostream>
#include <sstream>
#include <map>
#include <winhttp.h>
#pragma comment(lib, "winhttp.lib")
#include <Shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")
bool ParseUrl(const std::wstring &url, bool &is_https, int &url_port, std::wstring &url_host, std::wstring &url_path) {
bool fok = false;
do {
std::wstring::size_type protocol_pos = url.find(L"://");
if (protocol_pos == std::wstring::npos) {
break;
}
std::wstring url_protocol = url.substr(0, protocol_pos);
if (url_protocol == L"http") {
is_https = false;
}
else if (url_protocol == L"https") {
is_https = true;
}
else {
break;
}
std::wstring::size_type host_pos = url.find(L"/", protocol_pos + 3);
std::wstring sub_url = url.substr(0, host_pos);
if (host_pos == std::wstring::npos) {
std::wstring::size_type port_pos = sub_url.rfind(L":");
if (port_pos == protocol_pos) {
url_port = 0;
url_host = url.substr(protocol_pos + 3, host_pos - protocol_pos - 3);
}
else {
std::wstring port_str = sub_url.substr(port_pos + 1);
url_port = StrToIntW(port_str.c_str());
url_host = url.substr(protocol_pos + 3, port_pos - protocol_pos - 3);
}
url_path = std::wstring();
fok = true;
break;
}
else {
std::wstring::size_type port_pos = sub_url.rfind(L":");
if (port_pos == protocol_pos) {
url_port = 0;
url_host = url.substr(protocol_pos + 3, host_pos - protocol_pos - 3);
}
else {
std::wstring port_str = sub_url.substr(port_pos + 1, host_pos - port_pos - 1);
url_port = StrToIntW(port_str.c_str());
url_host = url.substr(protocol_pos + 3, port_pos - protocol_pos - 3);
}
url_path = url.substr(host_pos);
fok = true;
}
} while (false);
return fok;
}
std::string HttpRequestGet(const wchar_t *url, int& http_code, std::map<std::string, std::string> &headers) {
bool fok = false;
HINTERNET hSession = NULL;
HINTERNET hConnect = NULL;
HINTERNET hRequest = NULL;
std::string payload = "";
do {
std::wstring url_host = L"";
std::wstring url_path = L"";
bool is_https = false;
int url_port = 0;
if (!ParseUrl(url, is_https, url_port, url_host, url_path)) {
break;
}
// 创建一个会话
hSession = WinHttpOpen(L"User-Agent", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
if (hSession == NULL) {
break;
}
//设置请求超时时间
if (!WinHttpSetTimeouts(hSession, 1000, 1000, 1000, 1000)) {
break;
}
//https 请求设置协议
if (is_https) {
DWORD secure_protocols = WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2;
if (!::WinHttpSetOption(hSession, WINHTTP_OPTION_SECURE_PROTOCOLS, &secure_protocols, sizeof(secure_protocols))) {
break;
}
}
//设置重定向,直接返回响应码30X,此处的设置将影响后面的httcode码的返回
DWORD redirct_protocols = WINHTTP_OPTION_REDIRECT_POLICY_NEVER;
if (!::WinHttpSetOption(hSession, WINHTTP_OPTION_REDIRECT_POLICY, &redirct_protocols, sizeof(redirct_protocols))) {
break;
}
INTERNET_PORT connect_port = 0;
if (is_https && url_port == 0) {
connect_port = INTERNET_DEFAULT_HTTPS_PORT;
}
else if (!is_https && url_port == 0) {
connect_port = INTERNET_DEFAULT_HTTP_PORT;
}
else if (url_port != 0) {
connect_port = url_port;
}
DWORD dwReadBytes, dwSizeDW = sizeof(dwSizeDW), dwIndex = 0;
hConnect = WinHttpConnect(hSession, url_host.c_str(), connect_port, 0);
if (!hConnect) {
break;
}
hRequest = WinHttpOpenRequest(hConnect, L"GET", url_path.c_str(), L"HTTP/1.1", WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_REFRESH);
if (!hRequest) {
break;
}
//连接服务端,发送请求
if (!WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, NULL, 0, 0, 0)) {
break;
}
//响应请求
BOOL bResults = FALSE;
bResults = WinHttpReceiveResponse(hRequest, 0);
if (!bResults) {
break;
}
if (bResults) {
LPVOID lpOutBuffer = NULL;
LPVOID lpOutStatusBuffer = NULL;
DWORD dwSize = 0;
unsigned int ret_code = 0;
int temp;
//此处的参数与获取响应的Header参数不同
WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF,
WINHTTP_HEADER_NAME_BY_INDEX, NULL,
&dwSize, WINHTTP_NO_HEADER_INDEX);
// Allocate memory for the buffer.
DWORD headers_error = GetLastError();
if (headers_error == ERROR_INSUFFICIENT_BUFFER ) {
temp = dwSize / sizeof(WCHAR);
lpOutBuffer = new WCHAR[temp];
// Now, use WinHttpQueryHeaders to retrieve the header.
//请求返回所有的标头:WINHTTP_QUERY_RAW_HEADERS_CRLF
bResults = WinHttpQueryHeaders(hRequest,
WINHTTP_QUERY_RAW_HEADERS_CRLF,
WINHTTP_HEADER_NAME_BY_INDEX,
lpOutBuffer, &dwSize,
WINHTTP_NO_HEADER_INDEX);
temp = 6 / sizeof(WCHAR);
lpOutStatusBuffer = new WCHAR[temp];
// Now, use WinHttpQueryHeaders to retrieve the header.
//请求返回响应码:WINHTTP_QUERY_STATUS_CODE
bResults = WinHttpQueryHeaders(hRequest,
WINHTTP_QUERY_STATUS_CODE,
WINHTTP_HEADER_NAME_BY_INDEX,
lpOutStatusBuffer, &dwSize,
WINHTTP_NO_HEADER_INDEX);
http_code = StrToIntW((WCHAR*)lpOutStatusBuffer);
delete[] lpOutBuffer;
delete[] lpOutStatusBuffer;
}
}
/* std::stringstream ss;
while (1) {
char buf[1024];
dwReadBytes = 0;
WinHttpReadData(hRequest, buf, 1024, &dwReadBytes);
if (!dwReadBytes)
{
break;
}
ss.write(buf, dwReadBytes);
}
payload = ss.str();
*/
fok = true;
} while (FALSE);
if (hSession) {
WinHttpCloseHandle(hSession);
}
if (hConnect) {
WinHttpCloseHandle(hConnect);
}
if (hRequest) {
WinHttpCloseHandle(hRequest);
}
return payload;
}
winhttp 获取httpcode 重定向code返回
最新推荐文章于 2024-03-29 11:07:12 发布