|
Introduction
This article explains how to set a proxy using PAC files. PAC files are Proxy Automatic Configuration files, which define a proxy for a specific URL. The solution presented in the article uses the WinHttp.dll for obtaining a proxy URL.
Background
- PAC files information: Proxy Auto-Config File Format.
- WinHttp library information: Microsoft Library.
Using the code
I’ve created a simple testing application that sends a web request to www.google.com using a proxy obtained from a PAC file.
In order to run the application you need to put the proxy.pac file into your home directory for the default web site. Usually this directory is c:\inetpub\wwwroot.
The main function that returns the proxy for a specific URL is GetProxyForUrlUsingPac
that is defined in the Proxy
class:
public static string GetProxyForUrlUsingPac ( string DestinationUrl, string PacUri ){
IntPtr WinHttpSession = Win32Api.WinHttpOpen("User",
Win32Api.WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
IntPtr.Zero,
IntPtr.Zero,
0);
Win32Api.WINHTTP_AUTOPROXY_OPTIONS ProxyOptions =
new Win32Api.WINHTTP_AUTOPROXY_OPTIONS();
Win32Api.WINHTTP_PROXY_INFO ProxyInfo =
new Win32Api.WINHTTP_PROXY_INFO();
ProxyOptions.dwFlags = Win32Api.WINHTTP_AUTOPROXY_CONFIG_URL;
ProxyOptions.dwAutoDetectFlags = (Win32Api.WINHTTP_AUTO_DETECT_TYPE_DHCP |
Win32Api.WINHTTP_AUTO_DETECT_TYPE_DNS_A);
ProxyOptions.lpszAutoConfigUrl = PacUri;
// Get Proxy
bool IsSuccess = Win32Api.WinHttpGetProxyForUrl( WinHttpSession,
DestinationUrl,
ref ProxyOptions,
ref ProxyInfo );
Win32Api.WinHttpCloseHandle(WinHttpSession);
if ( IsSuccess ){
return ProxyInfo.lpszProxy;
}else {
Console.WriteLine("Error: {0}", Win32Api.GetLastError() );
return null;
}
}
The Win32Api
class contains a definition of the Win32 functions:
/// <summary>
/// This function implements the Web Proxy Auto-Discovery (WPAD) protocol
/// for automatically configuring the proxy settings for an HTTP request.
/// The WPAD protocol downloads a Proxy Auto-Configuration (PAC) file,
/// which is a script that identifies the proxy server to use for a given
/// target URL. PAC files are typically deployed by the IT department within
/// a corporate network environment. The URL of the PAC file can either be
/// specified explicitly or WinHttpGetProxyForUrl can be instructed to
/// automatically discover the location of the PAC file on the local network.
/// </summary>
/// <param name="hSession">The WinHTTP session handle
/// returned by the WinHttpOpen function</param>
/// <param name="lpcwszUrl">A pointer
/// to a null-terminated Unicode string that contains the
/// URL of the HTTP request that the application is preparing to send.</param>
/// <param name="pAutoProxyOptions">A pointer
/// to a WINHTTP_AUTOPROXY_OPTIONS structure that
/// specifies the auto-proxy options to use.</param>
/// <param name="pProxyInfo">A pointer
/// to a WINHTTP_PROXY_INFO structure that receives the
/// proxy setting. This structure is then applied to the request handle using the
/// WINHTTP_OPTION_PROXY option.</param>
/// <returns></returns>
[DllImport("winhttp.dll", SetLastError=true, CharSet=CharSet.Unicode)]
public static extern bool WinHttpGetProxyForUrl(
IntPtr hSession,
string lpcwszUrl,
ref WINHTTP_AUTOPROXY_OPTIONS pAutoProxyOptions,
ref WINHTTP_PROXY_INFO pProxyInfo);
/// <summary>
/// The function initializes, for an application, the use of WinHTTP
/// functions and returns a WinHTTP-session handle
/// </summary>
/// <param name="pwszUserAgent">A pointer
/// to a string variable that contains the name of the
/// application or entity calling the WinHTTP functions.</param>
/// <param name="dwAccessType">Type of access required.
/// This can be one of the following values</param>
/// <param name="pwszProxyName"> A pointer
/// to a string variable that contains the name of the
/// proxy server to use when proxy access
/// is specified by setting dwAccessType to
/// WINHTTP_ACCESS_TYPE_NAMED_PROXY. The WinHTTP functions
/// recognize only CERN type proxies for HTTP.
/// If dwAccessType is not set to WINHTTP_ACCESS_TYPE_NAMED_PROXY,
/// this parameter must be set
/// to WINHTTP_NO_PROXY_NAME</param>
/// <param name="pwszProxyBypass">A pointer
/// to a string variable that contains an optional list
/// of host names or IP addresses, or both,
/// that should not be routed through the proxy when
/// dwAccessType is set to WINHTTP_ACCESS_TYPE_NAMED_PROXY.
/// The list can contain wildcard characters.
/// Do not use an empty string, because
/// the WinHttpOpen function uses it as the proxy bypass list.
/// If this parameter specifies the "<local>" macro
/// as the only entry, this function bypasses
/// any host name that does not contain a period.
/// If dwAccessType is not set to WINHTTP_ACCESS_TYPE_NAMED_PROXY,
/// this parameter must be set to WINHTTP_NO_PROXY_BYPASS.</param>
/// <param name="dwFlags">Unsigned long integer value
/// that contains the flags that indicate various options
/// affecting the behavior of this function</param>
/// <returns>Returns a valid session handle
/// if successful, or NULL otherwise</returns>
[DllImport("winhttp.dll", SetLastError=true, CharSet=CharSet.Unicode)]
public static extern IntPtr WinHttpOpen(
string pwszUserAgent,
int dwAccessType,
IntPtr pwszProxyName,
IntPtr pwszProxyBypass,
int dwFlags
);
/// <summary>
/// The function closes a single HINTERNET handle
/// </summary>
/// <param name="hInternet">Valid HINTERNET handle to be closed.</param>
/// <returns>Returns TRUE if the handle
/// is successfully closed, or FALSE otherwise</returns>
[DllImport("winhttp.dll", SetLastError=true, CharSet=CharSet.Unicode)]
public static extern bool WinHttpCloseHandle(IntPtr hInternet);
The main function that uses the GetProxyForUrlUsingPac
is:
// Create test request
WebRequest TestRequest = WebRequest.Create ( DestinationUrl );
// Optain Proxy address for the URL
string ProxyAddresForUrl = Proxy.GetProxyForUrlUsingPac (DestinationUrl, PacUri);
if ( ProxyAddresForUrl != null ){
Console.WriteLine ("Found Proxy: {0}", ProxyAddresForUrl );
TestRequest.Proxy = new WebProxy ( ProxyAddresForUrl ) ;
}else{
Console.WriteLine ( "Proxy Not Found. Send request directly." );
}
That's it.
License
This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.
A list of licenses authors might use can be found here
About the Author
| Glaxalg
Software Developer (Senior)
United States
Member
|
Hi,
i have following Problem:
I use Winhttp as API to transfer http packets, to allow my program to use of Proxy, I try first
WinHttpGetProxyForUrl with
AutoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
AutoProxyOptions.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A;
to use auto detection
if this fails, i call
WinHttpGetIEProxyConfigForCurrentUser
where I either get the Proxy direct (which works fine) or i get the PAC-URL
in the case of PAC-URL then I call WinHttpGetProxyForUrl again with
AutoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
AutoProxyOptions.dwAutoDetectFlags=0;
AutoProxyOptions.lpszAutoConfigUrl=l_ProxyConfig.lpszAutoConfigUrl;
When i make this call i get the errorcode 12006 which means
ERROR_WINHTTP_UNRECOGNIZED_SCHEME. But the l_ProxyConfig.lpszAutoConfigUrl=_T("http://mypc.lan.at/proxy.pac") which seems ok for me...
Does anybody knows a fix for that problem, or what I have done wrong?
thanks in advance
Wolfgang-h