Virtual Hosting: PAC

From The Uniform Server Wiki
Revision as of 21:41, 5 July 2008 by Ric (talk | contribs)
Jump to navigation Jump to search

MPG UniCenter

Virtual Hosting: Home | Name based | PAC | Browsers and PAC | Making it portable | Issues

PAC and Portability
Uniform Server 3.5-Apollo

On the previous page I covered name-based virtual hosting it uses the local machines Hosts file to resolve domain names. To run a portable development server you need to edit the new target PC’s Hosts file. This page looks at resolving this issue using a PAC file and a portable browser making the server completely portable.

PAC allows you to simulate a DNS server locally one line per CNAME entry. Unlike the hosts file it is dynamic. PAC is a standard uses a single file and is supported by all new browsers.

Ever had problems testing sites with a mix of relative, root relative and absolute links ever wanted to test cross-site interlinking the following trio may be what you are looking for. Uniform Server, portable (Firefox or Opera) and PAC make an ideal test environment all on a USB memory stick.

In the light of issues raised overall Firefox portable is the best option.

Background

Testing multi-web sites is relatively easy; first create a virtual host section for each site in the Apache configuration file. Use the hosts file on your machine to resolve web site IP address that’s it finished. Suppose you do not have access to the host file what alternatives are there.

If you use only relative links on your site you can use the Apache alias and re-map however if your sites are using absolute or root relative links this method will fail.

Not looking very good, what other methods are there for resolving IP addresses. A local DNS server would do nicely even allow you to enter MX records. That seems a bit of overkill, all we want to do is convince our browser to pick up pages from a different server masquerading as the real server enter the world of proxy servers.

Top

PAC

Web browsers can be configured to use a proxy server allowing the use of files or other resource available on a different server.

This process is automated with a Proxy Auto-Configuration (PAC) file. Sounds complicated, not really the PAC file is a simple text file containing a few instructions.

Just tell your browser where to find it by setting the appropriate options. Your browser reads this file when it is re-started and whenever it needs to resolve an IP address.

Any special instruction are executed before your browser attempts to resolve an IP address this is why PAC is so powerful.

Top

PAC file

The PAC file is a JavaScript consisting of single function. This function receives two parameters (url and host).
Parameters are automatically provided by a browser.


Your browser calls the function using the following line: ret = FindProxyForURL(url, host);

PAC File
function FindProxyForURL(url, host)

{
  ...
}

  • url

The full URL being accessed e.g.: http://wiki.uniformserver.com/index.php/Main_Page

  • host

The hostname extracted from the URL. It is the string between :// and the first : or / after that e.g.
http://wiki.uniformserver.com/index.php/Main_Page
Note 1: The port number is not included. If required can be extracted from the URL.

  • ret
The return value a string describing the configuration.

Return Value:

The JavaScript function must return a single string if the string is null, no proxies shall be used. The string can contain any of the following blocks, separated by a semicolon:

DIRECT Connections should be made directly, without any proxies.
PROXY host;port The specified proxy should be used. It's this return value we are interested in
SOCKS host;port The specified SOCKS server should be used.

There are a number of predefined functions you can use we are interested in only two shExpMatch and dnsDomainIs.

If these do not suit your needs you can easily find more information on the Internet this isworth a read Navigator Proxy Auto-Config File Format.

Top

Compare function

This function compares two strings I think the only special character it accepts is the wildcard character * (matches one or more characters) not a limitation probably makes it easier to use. The function has this format:

shExpMatch(str, shexp)

  • str

any string to be compared for example the URL or the hostname.

  • shexp

the expression to compare against can use the wildcard character.

The function returns true if the string matches the specified expression.

Examples:

shExpMatch("http://home.unicenter.com/site1/index.html", "*site1*") is true.
shExpMatch("http://home.unicenter.com/site2/index.html", "*site1*") is false.

The above is just an example, replace the fixed string with a variable such as the url for example:

(shExpMatch(url, "*site1*");

Any url passed to the above function containing the string site1 (anywhere) will produce true.

The result can be can be filtered using an if statement. If true do something else continue onto the next line of code.

Filter

if (shExpMatch(url,"*site1*")) return "PROXY 127.0.0.1";

The comparison is true, the something to do is to return an IP address of a proxy server. The url our browser was looking for can be found on the proxy server 127.0.0.1 (that's our local test server) Its this return value that resolves the IP address hence the browser is happy and fetches the information.

Top

Complete PAC file

Add this filter to the PAC function and we have our very own DNS resolver, with the ability to define any CNAME that we wish.

test.pac File

function FindProxyForURL(url, host)
{
  if (shExpMatch(url,"*site1*")) return "PROXY 127.0.0.1";
  return "";
}

Note: If a match is not found the function returns a null value. This means the poor old browser needs to do a little more work to resolve the IP address. It checks the hosts file then any local DNS server, as a last resort puts a request onto the Internet to a DNS server.

Top

PAC and Hosts file

From the previous page we have the following entries in the Hosts file:

  • 127.0.0.1 www.my_site1.fredtest.mine.nu
  • 127.0.0.1 www.my_site2.fredtest.mine.nu
  • 127.0.0.1 www.ric.com

With a PAC file specific strings can be targetted, we are interested in is resolving domain names not what is typed into a browser. I have highlighted in bold these domain names. There are only two domains to resolve mine.nu and ric.com hence our PAC file requires two lines as follows:

test.pac File
function FindProxyForURL(url, host)
{
  if (shExpMatch(url,"*.mine.nu/*")) return "PROXY 127.0.0.1";
  if (shExpMatch(url,"*.ric.com/*")) return "PROXY 127.0.0.1";
  return "";
} 

Alternative function

If you do not like using wild cards you can use the function dnsDomainIs to directly target a domain name.

dnsDomainIs(host, domain)

  • host

is the hostname from the URL e.g http://wiki.uniformserver.com/index.php/Main_Page

  • domain

is the domain name to test the hostname against e.g. .uniformserver.com

Returns true if the domain of hostname matches.

test1.pac File
function FindProxyForURL(url, host)
{
  if (dnsDomainIs(host,".mine.nu")) return "PROXY 127.0.0.1";
  if (dnsDomainIs(host,".ric.com")) return "PROXY 127.0.0.1";
  return "";
} 

Top

Mimic Hosts file

You can mimic the host file as follows:

test2.pac File
function FindProxyForURL(url, host)
{
  if (shExpMatch(url,"http://www.my_site1.fredtest.mine.nu/*")) return "PROXY 127.0.0.1";
  if (shExpMatch(url,"http://www.my_site2.fredtest.mine.nu/*")) return "PROXY 127.0.0.1";
  if (shExpMatch(url,"http://www.ric.com/*")) return "PROXY 127.0.0.1";
  return "";
} 

Top

Feedback from forum (27-6-07)

This was posted by figment88 and provides another interesting way to use a PAC file; you can read the full post here Uniform Forum. All I have done is a cut and past job.

I wanted to add an extra tip on top of the UniCenter tutorial. The tutorial shows you how to setup a proxy file so you can have name based virtual hosts without modifying the current computer's HOST file. The examples in the tutorial require you to modify your proxy file (*.pac) to add a line for every new virtual host. In addition, the examples use wildcard matching, so if you name your local site "example" and the real site is "example.com" the browser might not let you load both.

I made a simple proxy file that solves both these issues

figment88.pac
function FindProxyForURL(url, host) {

if(isPlainHostName(host)) return "PROXY 127.0.0.1";

return "DIRECT";
} 

The isPlainHostName looks for hosts that have a dot. So, I always name my local version of a website as a single word; e.g,

site1 is site1.com
site2 is site2.com


Comment: My original pact file contained wildcard matching not intentional since I specially wanted to target each site and prevent my browser looking on the Internet. I have included both versions for completness. In contrast figment88 wants to view his development site locally and the published version hence his neat solution.

Summary

The above was just a quick introduction to the PAC file; it is much more powerful and worth further investigation search the Internet for more information. I have only covered what we need for our purpose. The test.pac file is about as complex as it gets.

On the next page I show how to plumb the PAC file into your browser.

Top


Ric