winhttp 获取httpcode 重定向code返回

#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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值