PAC Files and the Inconstant Constant

Recently, I was working on an update for the PAC files we use at work. Had a clever idea for making clients more resilient in the event of an individual proxy failing – just list all the proxies in the PAC file, and use a bit of MATH to spread the load. This initially failed, but not for any of the reasons you might expect…

Here’s the relevant subset of code:

const PROXIES = ["10.1.1.1", "10.1.1.2", "10.1.1.3",
                 "10.1.1.4", "10.1.1.5", "10.1.1.6"];

// this could be any number really, it just has to be defined
hash = 42;


// other typical PAC file stuff would go here

ipStr = myIpAddress();
for (i = 0; i < ipStr.length; i++) {
  hash += ipStr.charCodeAt(i);
}

// this will be between 0 and (numProxies - 1) 
baseProxy = (hash % PROXIES.length);

// You could also use something like
// for (j=1; j <= (PROXIES.length / 2); j++) 
for (j=1; j <= 3; j++) {
  retStr += "PROXY " + PROXIES[baseProxy] + ":3128; " ;
  baseProxy += 1;
  if (baseProxy >= PROXIES.length) baseProxy = 0;
}

retStr += "DIRECT";
return retStr;

As part of a well-balanced FindProxyForURL() function, the above will return something like

PROXY 10.1.1.5:3128; PROXY 10.1.1.6:3128; PROXY 10.1.1.1:3128; DIRECT

It parses myIpAddress(), which should be fairly random and different for every client. We treat it like a string, instead of trying to parse the IP address itself, which means it should work even when the client has multiple NICs, multiple IP addresses, IPv4 and IPv6 addresses, and so on. Internal testing has shown that over a large enough user base, this should be effectively random (i.e. the clients will be split over all proxies).

And it worked pretty well! Except on some very old clients. Specifically, Internet Explorer 11, on Windows 7, just failed completely to use the proxy.

It was not a network problem, because clients could be manually pointed to a proxy and all was well. And it was not a problem with the PAC file, because other browsers on that machine (Chrome and Firefox) worked well too.

The problem was very subtle — the “const” keyword. Since the array of proxies won’t change, I tagged it as a constant, just to be sure any sloppy programming on my part wouldn’t scribble on the list of proxies and cause problems.

The “const” keyword was added to JavaScript in 2015, and while it works well enough for client-facing code (i.e. JavaScript in a Web page), this particular feature seems not to have been back-ported to whatever little subset of JavaScript they use for PAC parsing specifically.

PAC files are JavaScript, except when they’re not, I suppose.

My best takeaway from this is another tool for Uncle Dave’s Proxy Toolbox, autoprox. This Windows command-line tool does PAC file testing, similar to pacparser, but it uses Windows’ own APIs to do the parsing instead of including its own bundled JS interpreter.

PAC Files and the Inconstant Constant