• Download source files - 7.59 Kb
  • Download demo project - 2.87 Kb

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 theWinHttp.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 isc:\inetpub\wwwroot.

The main function that returns the proxy for a specific URL is GetProxyForUrlUsingPac that is defined in theProxy 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 requestWebRequest TestRequest = WebRequest.Create ( DestinationUrl );           // Optain Proxy address for the URLstring 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.