Moozz
Moozz

Reputation: 609

What is the best way to use .PAC in C# when request is redirected

Background

I have to use the proxy server specified by users in my application. Right now, I check that the input proxy contains ".pac" or not. If yes, I'll get the real proxy from pac file. (http://www.codeproject.com/Articles/12168/Using-PAC-files-proxy) Otherwise, I just set the input proxy to WebProxy.

public HttpWebRequest CreateRequest(string url, string proxy)
{
    var request = WebRequest.Create(url);
    if (proxy.ToLower().Contains(".pac")) 
    {
        string realProxy = GetProxyFromPac(url, proxy);
        request.Proxy = (string.IsNullOrEmpty(realProxy)) 
            ? new WebProxy() 
            : new WebProxy(realProxy, true);
    }
    else
    {
        request.Proxy = new WebProxy(proxy, true);
    }
    return request as HttpWebRequest;
}

And use the request like this.

var request = CreateRequest(url, proxy);
var response = request.GetResponse() as HttpWebResponse;

Problem

When the server redirects url to another url, I'll get request timeout.

Example:

I found that it's because I set the proxy to P in the request and it will be used for all urls (including redirected urls) but REAL_URL is not accessible via P. I have to get PP from the REAL_URL and PAC_P and use PP to request to REAL_URL.

The first solution in my head is to get a new proxy every time the request is redirected and manually request to the redirected url.

var request = CreateRequest(url, proxy);
request.AllowAutoRedirect = false;
var response = request.GetResponse() as HttpWebResponse;
while (response.StatusCode == HttpStatusCode.Redirect ||
       response.StatusCode == HttpStatusCode.Moved)
{
    request = CreateRequest(response.Headers["Location"], proxy);
    response = request.GetResponse() as HttpWebResponse;
}

Question

I think there should be an elegant way to handle this. It seems to be an extremely general case. Do you have any idea?

Upvotes: 1

Views: 3064

Answers (1)

runTarm
runTarm

Reputation: 11547

You can implement your own IWebProxy class like this:

public class MyPacScriptProxy : IWebProxy
{
    protected string PacScriptUrl;

    public MyPacScriptProxy(string url)
    {
        PacScriptUrl = url;
    }

    public ICredentials Credentials { get; set; }

    public Uri GetProxy(Uri dest)
    {
        // you can return your GetProxyFromPac(dest, PacScriptUrl); result here

        if (dest.Host.EndsWith(".net")) {
            return null; // bypass proxy for .net websites
        }

        return new Uri("http://localhost:8888");
    }

    public bool IsBypassed(Uri host)
    {
        return false;
    }
}

then use it like this:

var request = WebRequest.Create("http://www.google.com");
request.Proxy = new MyPacScriptProxy("http://localhost/proxy.pac");

Hope this helps :)

Upvotes: 2

Related Questions