7.4 Proxies


Many systems access the Web and sometimes other non-HTTP parts of the Internet through proxy servers . A proxy server receives a request for a remote server from a local client. The proxy server makes the request to the remote server and forwards the result back to the local client. Sometimes this is done for security reasons, such as to prevent remote hosts from learning private details about the local network configuration. Other times it's done to prevent users from accessing forbidden sites by filtering outgoing requests and limiting which sites can be viewed . For instance, an elementary school might want to block access to http://www.playboy.com. And still other times it's done purely for performance, to allow multiple users to retrieve the same popular documents from a local cache rather than making repeated downloads from the remote server.

Java programs based on the URL class can work through most common proxy servers and protocols. Indeed, this is one reason you might want to choose to use the URL class rather than rolling your own HTTP or other client on top of raw sockets.

7.4.1 System Properties

For basic operations, all you have to do is set a few system properties to point to the addresses of your local proxy servers. If you are using a pure HTTP proxy, set http.proxyHost to the domain name or the IP address of your proxy server and http.proxyPort to the port of the proxy server (the default is 80). There are several ways to do this, including calling System.setProperty() from within your Java code or using the -D options when launching the program. This example sets the proxy server to and the port to 9000:

 %  java -Dhttp.proxyHost=  -Dhttp.proxyPort=9000    com.domain.Program   

If you want to exclude a host from being proxied and connect directly instead, set the http.nonProxyHosts system property to its hostname or IP address. To exclude multiple hosts, separate their names by vertical bars. For example, this code fragment proxies everything except java.oreilly.com and xml.oreilly.com :

 System.setProperty("http.proxyHost", ""); System.setProperty("http.proxyPort", "9000"); System.setProperty("http.nonProxyHosts", "java.oreilly.comxml.oreilly.com"); 

You can also use an asterisk as a wildcard to indicate that all the hosts within a particular domain or subdomain should not be proxied. For example, to proxy everything except hosts in the oreilly.com domain:

 %  java -Dhttp.proxyHost=  -Dhttp.nonProxyHosts=*.oreilly.com    com.domain.Program   

If you are using an FTP proxy server, set the ftp.proxyHost , ftp.proxyPort , and ftp.nonProxyHosts properties in the same way.

Java does not support any other application layer proxies, but if you're using a transport layer SOCKS proxy for all TCP connections, you can identify it with the socksProxyHost and socksProxyPort system properties. Java does not provide an option for nonproxying with SOCKS. It's an all-or-nothing decision.

7.4.2 The Proxy Class

Java 1.5 allows more fine-grained control of proxy servers from within a Java program. Specifically, this allows you to choose different proxy servers for different remote hosts. The proxies themselves are represented by instances of the java.net.Proxy class. There are still only three kinds of proxies, HTTP, SOCKS, and direct connections (no proxy at all), represented by three constants in the Proxy.Type enum:

  • Proxy.Type.DIRECT

  • Proxy.Type.HTTP

  • Proxy.Type.SOCKS

Besides its type, the other important piece of information about a proxy is its address and port, given as a SocketAddress object. For example, this code fragment creates a Proxy object representing an HTTP proxy server on port 80 of proxy.example.com :

 SocketAddress address = new InetSocketAddress("proxy.example.com", 80); Proxy proxy = new Proxy(Proxy.Type.HTTP, address); 

Although there are only three kinds of proxy objects, there can be many proxies of the same type for different proxy servers on different hosts.

7.4.3 The ProxySelector Class

Each running Java 1.5 virtual machine has a single java.net.ProxySelector object it uses to locate the proxy server for different connections. The default ProxySelector merely inspects the various system properties and the URL's protocol to decide how to connect to different hosts. However, you can install your own subclass of ProxySelector in place of the default selector and use it to choose different proxies based on protocol, host, path , time of day, or other criteria.

The key to this class is the abstract select( ) method:

 public abstract List<Proxy> select(URI uri) 

Java passes this method a URI object (not a URL object) representing the host to which a connection is needed. For a connection made with the URL class, this object typically has the form http://www.example.com/ or ftp://ftp.example.com/pub/files/ , or some such. For a pure TCP connection made with the Socket class, this URI will have the form socket://host:port :, for instance, socket://www.example.com:80 . The ProxySelector object then chooses the right proxies for this type of object and returns them in a List<Proxy> .

The second abstract method in this class you must implement is connectFailed( ) :

 public void connectFailed(URI uri, SocketAddress address, IOException ex) 

This is a callback method used to warn a program that the proxy server isn't actually making the connection. Example 7-11 demonstrates with a ProxySelector that attempts to use the proxy server at proxy.example.com for all HTTP connections unless the proxy server has previously failed to resolve a connection to a particular URL. In that case, it suggests a direct connection instead.

Example 7-11. A ProxySelector that remembers what it can connect to
 import java.net.*; import java.util.*; import java.io.*; public class LocalProxySelector extends ProxySelector {      private List failed = new ArrayList( );      public List<Proxy> select(URI uri) {          List<Proxy> result = new ArrayList<Proxy>( );     if (failed.contains(uri)         "http".equalsIgnoreCase(uri.getScheme( ))) {         result.add(Proxy.NO_PROXY);     }     else {         SocketAddress proxyAddress            = new InetSocketAddress( "proxy.example.com", 8000);         Proxy proxy = new Proxy(Proxy.Type.HTTP, proxyAddress);         result.add(proxy);     }          return result;        }      public void connectFailed(URI uri, SocketAddress address, IOException ex) {     failed.add(uri);   }    } 

As I already said, each running virtual machine has exactly one ProxySelector . To change the ProxySelector , pass the new selector to the static ProxySelector.setDefault( ) method, like so:

 ProxySelector selector = new LocalProxySelector( ): ProxySelector.setDefault(selector); 

From this point forward, all connections opened by that virtual machine will ask the ProxySelector for the right proxy to use. You normally shouldn't use this in code running in a shared environment. For instance, you wouldn't change the ProxySelector in a servlet because that would change the ProxySelector for all servlets running in the same container.

Java Network Programming
Java Network Programming, Third Edition
ISBN: 0596007213
EAN: 2147483647
Year: 2003
Pages: 164

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net