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
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;
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:
[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);
[DllImport("winhttp.dll", SetLastError=true, CharSet=CharSet.Unicode)]
public static extern IntPtr WinHttpOpen(
string pwszUserAgent,
int dwAccessType,
IntPtr pwszProxyName,
IntPtr pwszProxyBypass,
int dwFlags
);
[DllImport("winhttp.dll", SetLastError=true, CharSet=CharSet.Unicode)]
public static extern bool WinHttpCloseHandle(IntPtr hInternet);
The main function that uses the GetProxyForUrlUsingPac
is:
WebRequest TestRequest = WebRequest.Create ( DestinationUrl );
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.