Selenium RC proxy chaining

Looks like I'm not the only one who needs to chain the Selenium RC proxy to another HTTP proxy. The docs are misleading, here's how to do it.

Selenium RC uses a built-in proxy server so that it can inject itself into the domain of the site being tested. Sometimes however, you need it to go through another proxy server.

The options documentation says you can supply http.proxyHost and http.proxyPort Java system properties to do this, which implies that requests that selenium makes will be proxied through that.

However, that doesn't actually happen for the domain under test; Selenium RC's proxy passes those straight onto the domain's server, without using the proxy.

(When supplying those options, the proxy.pac file that Selenium RC puts out looks like this:

function FindProxyForURL(url, host) {
        return 'PROXY localhost:4444; PROXY localhost:8090';
}

But that does not create a proxy chain – it just creates a failover chain, where the browser will use the Selenium RC proxy and only if that doesn't work will it use your proxy.)

For most cases though, there is a simple solution. We don't actually need our requests to the domain under test to pass through Selenium RC – we only need the requests for the selenium wrapper stuff to go to it, so that they appear in domain.

So if we can make the requests to /selenium-server/ go to Selenium RC, and everything else go straight to the other proxy server, everyone's happy.

You don't need to make your own proxy PAC files and explicitly start browsers, as there is a -avoidProxy Selenium RC option to do it.

For example:

java -Dhttp.proxyHost=localhost -Dhttp.proxyPort=8090 \
  -jar selenium-server.jar -avoidProxy

Which produces a proxy.pac file like this:

function FindProxyForURL(url, host) {
    if(shExpMatch(url, '*/selenium-server/*')) {
        return 'PROXY localhost:4444; PROXY localhost:8090';
    } else if (shExpMatch(host, 'local')) {
        return 'DIRECT';
    } else if (shExpMatch(host, '*.local')) {
        return 'DIRECT';
    } else if (shExpMatch(host, '169.254/16')) {
        return 'DIRECT';
    } else if (shExpMatch(host, '*.169.254/16')) {
        return 'DIRECT';
    } else {
        return 'PROXY localhost:8090';
    }
}

From this you can see that it will use our proxy on port 8090 as desired.

One catch you can also see, however, is that it will bypass the proxy for *.local sites – so don't use that as your hostname for the domain under test. Similarly, it bypasses the proxy for sites identified by IP address (rather than by name) and using just one (!?) of the private IP address ranges, so use named hosts instead.