Handling Proxy Auto Config (PAC) scripts in Java

The built in support for detecting proxies in Java is rather limited. In a recent project I ran into problems due to the lack of visible support for PAC (even though it is part of Java Web Start). In this post I outline how this can be solved by running JavaScript within a Java application and letting the JavaScript call methods defined in Java.

Before writing your own implementation it is worth noting that there are existing solutions available, e.g. Proxy Vole.

What is PAC?
Proxy auto-config was defined by Netscape for their Netscape Navigator 2.0 a long time ago (1996). It is a very dynamic method for configuring what proxy to use for accessing a specific URL. It works in the following way:

  • A PAC file holding a JavaScript is placed on a web server. The file is required to contain the following JavaScript function FindProxyForURL(url, host).
  • The client is told to use the PAC file. Either by configuring the URL or using WPAD. How to find the stored URL depends on the OS.
  • Before attempting to access a URL the client will call the JavaScript function FindProxyForURL(url, host) to get the proxy configuration to use. The configuration is in the form of a string with ; as separator, for example:

    This means use proxy1 to connect to the URL, if this fails don’t use any proxy.

Using JavaScript from within Java to Evaluating PAC scripts
How can the FindProxyForURL(url,host) possibly find what URL to use? The answer is that it can use a number of pre-defined functions, see Navigator Proxy Auto-Config File Format. At first look the number of functions looks daunting but most of them can easily be implemented. We wanted to use Java as much as possible and therefore created a Java class holding methods with the same signatures as the JavaScript functions. It is called PACScriptMethods in the example code below which shows how the PAC script can be evaluated:

The careful reader may have spotted that I left out the defineBridgeFunction(...). It generates the strings defining JavaScript methods that simply call the method in our Java object. For example defineBridgeFunction("myFunction", 2) results in:

This uses the binding set on the JavaScript engine to call the corresponding Java method (same name and number of arguments).

The proxy configuration in proxyConfig can now easily be parsed (remember “;” as separator) to create a list of standard Java Proxy objects holding the proxy settings.

Leave a Reply