WinHTTP AutoProxy 函数
WinHTTP 使用 WinHttpGetProxyForUrl 函数以及两个支持的实用工具函数 WinHttpDetectAutoProxyConfigUrl 和 WinHttpGetIEProxyConfigForCurrentUser 实现 WPAD 协议。
AutoProxy 支持未完全集成到 WinHTTP 中的 HTTP 堆栈中。 在发送请求之前,应用程序必须调用 WinHttpGetProxyForUrl 以获取代理服务器的名称,然后使用WINHTTP_OPTION_PROXY调用 WinHttpSetOption 来设置 WinHttpOpenRequest 创建的 WinHTTP 请求句柄上的代理配置。
WinHttpGetProxyForUrl 函数可执行上述概述中所述的 WPAD 协议的所有三个步骤: (1) 发现 PAC URL, (2) 下载 PAC 脚本文件, (3) 执行脚本代码,并在WINHTTP_PROXY_INFO结构中返回代理配置。 (可选)如果应用程序事先知道 PAC URL,则可以将其指定给 WinHttpGetProxyForUrl。
以下示例代码使用 autoproxy。 它通过首先创建 WinHTTP 会话连接和请求句柄来设置 HTTP GET 请求。 WinHttpOpen 调用指定初始代理配置的WINHTTP_ACCESS_TYPE_NO_PROXY,以指示默认情况下将请求直接发送到目标服务器。 然后,它使用 autoproxy 直接在请求句柄上设置代理配置。
HINTERNET hHttpSession = NULL;
HINTERNET hConnect = NULL;
HINTERNET hRequest = NULL;
WINHTTP_AUTOPROXY_OPTIONS AutoProxyOptions;
WINHTTP_PROXY_INFO ProxyInfo;
DWORD cbProxyInfoSize = sizeof(ProxyInfo);
ZeroMemory( &AutoProxyOptions, sizeof(AutoProxyOptions) );
ZeroMemory( &ProxyInfo, sizeof(ProxyInfo) );
//
// Create the WinHTTP session.
//
hHttpSession = WinHttpOpen( L"WinHTTP AutoProxy Sample/1.0",
WINHTTP_ACCESS_TYPE_NO_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS,
0 );
// Exit if WinHttpOpen failed.
if( !hHttpSession )
goto Exit;
//
// Create the WinHTTP connect handle.
//
hConnect = WinHttpConnect( hHttpSession,
L"www.microsoft.com",
INTERNET_DEFAULT_HTTP_PORT,
0 );
// Exit if WinHttpConnect failed.
if( !hConnect )
goto Exit;
//
// Create the HTTP request handle.
//
hRequest = WinHttpOpenRequest( hConnect,
L"GET",
L"ms.htm",
L"HTTP/1.1",
WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
0 );
// Exit if WinHttpOpenRequest failed.
if( !hRequest )
goto Exit;
//
// Set up the autoproxy call.
//
// Use auto-detection because the Proxy
// Auto-Config URL is not known.
AutoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
// Use DHCP and DNS-based auto-detection.
AutoProxyOptions.dwAutoDetectFlags =
WINHTTP_AUTO_DETECT_TYPE_DHCP |
WINHTTP_AUTO_DETECT_TYPE_DNS_A;
// If obtaining the PAC script requires NTLM/Negotiate
// authentication, then automatically supply the client
// domain credentials.
AutoProxyOptions.fAutoLogonIfChallenged = TRUE;
//
// Call WinHttpGetProxyForUrl with our target URL. If
// auto-proxy succeeds, then set the proxy info on the
// request handle. If auto-proxy fails, ignore the error
// and attempt to send the HTTP request directly to the
// target server (using the default WINHTTP_ACCESS_TYPE_NO_PROXY
// configuration, which the requesthandle will inherit
// from the session).
//
if( WinHttpGetProxyForUrl( hHttpSession,
L"https://www.microsoft.com/ms.htm",
&AutoProxyOptions,
&ProxyInfo))
{
// A proxy configuration was found, set it on the
// request handle.
if( !WinHttpSetOption( hRequest,
WINHTTP_OPTION_PROXY,
&ProxyInfo,
cbProxyInfoSize ) )
{
// Exit if setting the proxy info failed.
goto Exit;
}
}
//
// Send the request.
//
if( !WinHttpSendRequest( hRequest,
WINHTTP_NO_ADDITIONAL_HEADERS,
0,
WINHTTP_NO_REQUEST_DATA,
0,
0,
NULL ) )
{
// Exit if WinHttpSendRequest failed.
goto Exit;
}
//
// Wait for the response.
//
if( !WinHttpReceiveResponse( hRequest, NULL ) )
goto Exit;
//
// A response has been received, then process it.
// (omitted)
//
Exit:
//
// Clean up the WINHTTP_PROXY_INFO structure.
//
if( ProxyInfo.lpszProxy != NULL )
GlobalFree(ProxyInfo.lpszProxy);
if( ProxyInfo.lpszProxyBypass != NULL )
GlobalFree( ProxyInfo.lpszProxyBypass );
//
// Close the WinHTTP handles.
//
if( hRequest != NULL )
WinHttpCloseHandle( hRequest );
if( hConnect != NULL )
WinHttpCloseHandle( hConnect );
if( hHttpSession != NULL )
WinHttpCloseHandle( hHttpSession );
在提供的示例代码中,对 WinHttpGetProxyForUrl 的调用指示函数通过在 WINHTTP_AUTOPROXY_OPTIONS 结构中指定 WINHTTP_AUTOPROXY_AUTO_DETECT 标志来自动发现 代理自动 配置文件。 使用 WINHTTP_AUTOPROXY_AUTO_DETECT 标志需要代码指定一个或两个自动检测标志 (WINHTTP_AUTO_DETECT_TYPE_DHCP, WINHTTP_AUTO_DETECT_TYPE_DNS_A) 。 示例代码使用 WinHttpGetProxyForUrl 的自动检测功能,因为事先不知道 PAC URL。 如果在此方案中无法在网络上找到 PAC URL, 则 WinHttpGetProxyForUrl 将失败, (GetLastError 返回 ERROR_WINHTTP_AUTODETECTION_FAILED) 。
如果 PAC URL 是“提前已知”
如果应用程序知道 PAC URL,则可以在WINHTTP_AUTOPROXY_OPTIONS结构中指定它,并将 WinHttpGetProxyForUrl 配置为跳过自动检测阶段。
例如,如果 PAC 文件位于本地网络上的 URL“https://InternalSite/proxy-config.pac",则对 WinHttpGetProxyForUrl 的调用如下所示。
//
// Set up the autoproxy call.
//
// The proxy auto-config URL is known. Auto-detection
// is not required.
AutoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
// Set the proxy auto-config URL.
AutoProxyOptions. lpszAutoConfigUrl = L"https://InternalSite/proxy-config.pac";
// If obtaining the PAC script requires NTLM/Negotiate
// authentication, then automatically supply the client
// domain credentials.
AutoProxyOptions.fAutoLogonIfChallenged = TRUE;
//
// Call WinHttpGetProxyForUrl with our target URL. If auto-proxy
// succeeds, then set the proxy info on the request handle.
// If auto-proxy fails, ignore the error and attempt to send the
// HTTP request directly to the target server (using the default
// WINHTTP_ACCESS_TYPE_NO_PROXY configuration, which the request
// handle will inherit from the session).
//
if( WinHttpGetProxyForUrl( hHttpSession,
L"https://www.microsoft.com/ms.htm",
&AutoProxyOptions,
&ProxyInfo ) )
{
//...
如果 WINHTTP_AUTOPROXY_OPTIONS 结构同时指定 (WINHTTP_AUTOPROXY_AUTO_DETECT 和 WINHTTP_AUTOPROXY_CONFIG_URL 标志,并指定自动解除功能标志和) 自动配置 URL, 则 WinHttpGetProxyForUrl 首先尝试自动检测,如果自动检测无法找到 PAC URL,则“回退”到应用程序提供的自动配置 URL。
WinHttpDetectAutoProxyConfigUrl 函数
WinHttpDetectAutoProxyConfigUrl 函数实现 WPAD 协议的子集:它尝试自动检测代理自动配置文件的 URL,而无需下载或执行 PAC 文件。 在 Web 客户端应用程序必须处理 PAC 文件本身的下载和执行的特殊情况下,此函数非常有用。
WinHttpGetIEProxyConfigForCurrentUser 函数
WinHttpGetIEProxyConfigForCurrentUser 函数返回当前活动网络连接的当前用户 Internet Explorer 代理设置,而不调用“WinInet.dll”。 仅当在交互式用户帐户标识下运行的进程内调用时,此函数才有用,因为否则可能没有 Internet Explorer 代理配置可用。 例如,从 IIS 服务进程中运行的 ISAPI DLL 调用此函数将没有用。 有关详细信息,以及基于 WinHTTP 的应用程序将使用 WinHttpGetIEProxyConfigForCurrentUser 的方案,请参阅 没有自动配置文件的发现。