The following are some issues that I've found in my time writing and deploying PAC files. Sometimes even the most trivial functions can have serious repercussions on the network and browser performance, so be careful on what you put into your PAC file.
It is always important to keep that some browsers are case sensitive with respect to hosts. “www.ibm.com” is not the same as “WWW.IBM.COM” and won’t match the same rules in a PAC file. Granted, most of the world uses lower case, but you never quite know when you’re going to run into someone that might capitalize an acronym or a company name somewhere in their pages or in their code.
You can either simply hope that your users and sites they access stick to lower case or you can use some of the tips I mention later on in this section to convert everything to lower case.
Note: Most modern browsers simply convert all the host variables to lower case anyhow, so this probably isn’t a big deal anymore but it used to cause some challenges. If you haven’t seen this as a problem I wouldn’t worry about it too much.
Using isInNet(host, "a.b.c.d") can cause major chaos with your DNS infrastructure. This relatively innocuous looking function will force EVERY browser to perform a reverse DNS lookup on every unique hostname that it tries to contact that’s not already a simple IP address. This can rapidly have significant consequences, depending on how many workstations you have and how robust your DNS infrastructure is. This doesn’t necessary mean that you can’t use this function, but that you must do it carefully and understand the implications. See the "PAC File Tricks" section for one way that it can be used safely.
The function isResolvable and dnsResolve have very similar issues as the described above They forces a DNS query every time the PAC is parsed for every request. Be careful using this for the same reasons. If you have a problem that only one of these functions can solve, use it carefully. Ensure that you don’t do unrestricted lookups for all hosts. Use logic like "if the domain name is company.com and IsResolvable"
If you use these functions, unexpected behavior might result. For example, if you try to look up an invalid domain name it’s possible that there might be a 30+ second delay for the request as the client tries to resolve the name. It can also place a tremendous load on your company’s DNS infrastructure, so be careful of its capacity.
In aPAC file, it is perfectly valid to provide multiple proxy servers in the return. The browser will first try to use the first proxy and, should it timeout or appear to fail, retry the query on the second and then third and so on. Again, this sounds relatively harmless but Internet Explorer interprets "timeout" very loosely. Experience has shown that if a user tries to access a WEB PAGE that doesn’t respond back in a timely manner IE will decide that it is the result of a proxy timeout and start sending requests to the secondary proxy. Needless to say, if your proxies are geographically dispersed this can start to spray traffic all across the network. This could be potentially mitigated by doing very careful tuning with proxy and Internet Explorer timeouts. Summary: If you use these functions be very, very careful that your traffic is going where you expect it to and test it extensively under a number of failure scenarios.
In general, for the large enterprise, a Global Server Load Balancing solution (i.e. F5’s GTM, Cisco GSS, etc.) provides for far more efficient failover and redundancy across the board.
A "Feature" of Internet Explorer is that it only reads the PAC file once per hostname and then remembers the result for all future queries. This means that you cannot send traffic to http://www.company.com/foo.html via the proxy and http://www.company.com/bar.html browser direct by editing the PAC file. This is referred to by Microsoft as "Automatic Proxy Result Cache". More information is available on the Microsoft website – A direct link can be found in the References menu, under the Vendor links.
Microsoft Word has a feature called "SmartQuotes" which will replace your standard vertial quotes with very pretty indented quotes. This looks great in text, but these SmartQuotes aren't readable by a PAC file. Editing a PAC file in Word can result in all quotes getting SmartQuote-ified. Needless to say, this is messy. If this happens, copy-and-paste into Notepad and do a search/replace to move everything back to normal quotes. You can, of course, turn off SmartQuotes, but the million monkeys waiting to use your computer would be very dissapointed.
Lesson learned - Don't use Word to edit any configuration.
Notepad is a significantly.. safer.. editor than Word. It does, however, have it's drawbacks. I've seen it eat a configuration file when Word Wrap was turned on. It doesn't happen frequently, but it's best to turn OFF Word Wrap in Notepad before doing any major work.
All good programmers follow a simple rule. Thou Must Document Thy Code. In a PAC file, however, this should be somewhat moderated. Remember that this file could be downloaded 50+ times per day per workstation on your network. The more comments you put in, the bigger the file gets the more network bandwidth it takes and the slower it is to load. Resist the temptation to over-comment. At the same point, comments are important for historical tracking. You need to find the right mix of comments for your environment.
When using isInNet(myIpAddress(), ….) to find the local client IP address you will occasionally get an invalid response with Internet Explorer. This occurs when there are multiple active NIC’s in the machine. IE occasionally gets confused which was used to send the request and responds back to myIpAddress() with the wrong one. For example, if you have one NIC on a company network and one bound to a wireless access point myIpAddress() will occasionally return back the IP of the wireless NIC, even when communicating with the proxy across the corporate network. Past experience has shown this to happen vary rarely, but it *does* happen. Unfortunately, there is no rhyme or reason in why or when this occurs and it’s impossible to predict. In short, don’t absolutely depend on this returning 100% accurate data and be sure to put in a fallback condition if none of your standard IP subnet match.
This is an important concept to understand if you’ve chosen to use variables in your PAC file. JavaScript uses the equals sign in two very different ways, depending if you use one (=) or two (==) together.
A single equals sign is always used to set a variable to a value. "Set the variable X to the value 3" is written as "X = 3". If you write a function that says "if (X=3) { .... } it will always be true since what you’re really writing is "If you can successfully set the variable X to the value 3 do { …. }"
If you are trying to compare two values, use two equals signs - ==. This tells the system to do a compare and return a true/false value. If you want to check to SEE if the value of X is 3, you would use "if (X== 3) { .... }". If X has the value of 2, the IF will fail. If X is 3, it will succeed and whatever is between the braces will process.
A number of users have contacted me about issues with the isInNet function failing when the host being parsed is a domain name and not an IP address. Good sources have indicated that this occurs in Internet Explorer 8.0 and also the Microsoft .NET Framework 2.0 and likely has something to do with an IPv6 implementation. I have not yet been able to replicate this behavior, but I do have a solution – Resolve the IP address of the host first with dnsResolve and then do a match with isInNet to look for a subnet match. As mentioned above, be careful of doing this as it can cause more DNS queries and some odd behavior, but it can be used effectively in certain circumstances. Here’s an example of how this would normally be written in a PAC file:
if (isInNet(dnsResolve(host), "10.0.0.0", "255.0.0.0") ||
isInNet(dnsResolve(host), "172.16.0.0", "255.240.0.0") ||
isInNet(dnsResolve(host), "192.168.0.0", "255.255.0.0")) {
return "DIRECT";
}
That forces DNS resolution of the host variable and then compares that IP address against the subnet you specify using isInNet.
The “Fixed” way to do it would be to place the resolved host IP address in a variable, then reference that variable multiple times with isInNet.
hostip=dnsResolve(host);
if (isInNet(hostip, "10.0.0.0", "255.0.0.0") ||
isInNet(hostip, "172.16.0.0", "255.240.0.0") ||
isInNet(hostip, "192.168.0.0", "255.255.0.0")) {
return "DIRECT";
}
There are several links regarding this topic in the "References" menu, to the left.
It is very important to remember that a string value and a number value are stored and used very differently. The "93" stored in text is just that - A set of string characters, no different than any other text. The number 93 is a real number that can be manipulated. If you end up with a number stored as text that you use as a number you can convert it using the parseInt() function.
numvariable = parseInt(textvar);