Wednesday, October 30, 2013

Use URL class to talk HTTP and HTTPS through proxy

The example below shows how to use the java URL class to talk to HTTP/HTTPS web servers. If your machine connects to the internet through a proxy, the hostname and the port number of the proxy need to be passed to the URL class.

One way to find the proxy is to use the web browser. As an example, in IE, you can go to Tools --> Internet Options --> Connections --> Lan settings. In my case, it shows that the checkbox "Use automatic configurtion script" is chosen. By looking at the script, I can find the proxy hostname and port number. In the code below, I just use "your.proxy.host" and "your.proxy.port". Note that the system property names are different depending on if you are connecting to HTTP or HTTPS. But the proxy host and port number are the same.

When this program is run, it should print out the contents of two HTML files, one for HTTP(http://example.com), and the other for HTTPS(https://verisign.com).

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;

public class TestURL {

 public void testHttpURL() {
  System.out.println("\ntestHttpURL()");

  System.setProperty("http.proxyHost", "your.proxy.host");
  System.setProperty("http.proxyPort", "your.proxy.port");
  String hostName = "http://example.com";
  try {
   URL hp = new URL(hostName);
   URLConnection urlConn = hp.openConnection();
   System.out.println("urlConn is: " + urlConn);
   HttpURLConnection hpCon = (HttpURLConnection) urlConn;

   InputStream obj = (InputStream) hpCon.getInputStream();
   BufferedReader in = new BufferedReader(new InputStreamReader(obj));

   String inputLine;

   while ((inputLine = in.readLine()) != null)
    System.out.println(inputLine);
  } catch (Exception ex) {
   ex.printStackTrace();
  }
 }

 public void testHttpsURL() {
  System.out.println("\ntestHttpsURL()");

  System.setProperty("https.proxyHost", "your.proxy.host");
  System.setProperty("https.proxyPort", "your.proxy.port");

  String trustStore = "C:\\bea1032\\jrockit_160_14_R27.6.5-32\\jre\\lib\\security\\cacerts";
  String trustStorePassword = "changeit";
  System.setProperty("javax.net.ssl.trustStore", trustStore);
  System.setProperty("javax.net.ssl.trustStorePassword",trustStorePassword);

  String hostName = "https://verisign.com";
  try {
   URL hp = new URL(hostName);
   URLConnection urlConn = hp.openConnection();
   System.out.println("urlConn is: " + urlConn);
   HttpURLConnection hpCon = (HttpURLConnection) urlConn;

   InputStream obj = (InputStream) hpCon.getInputStream();
   BufferedReader in = new BufferedReader(new InputStreamReader(obj));

   String inputLine;
   while ((inputLine = in.readLine()) != null)
    System.out.println(inputLine);
  } catch (Exception ex) {
   ex.printStackTrace();
  }
 }

 public static void main(String args[]) {
  TestURL p = new TestURL();
  p.testHttpURL();
  p.testHttpsURL();
 }
}

Note that in the code for HTTPS, the trustStore and its password values are the default values used by java. So those lines can be commented out. You can however set trustStore to an empty value "" to see what will happen. An exception will be thrown. So that shows that the code does need the trust store. If you are connecting to a HTTPS web site and the default java trustStore cacerts does not contain the certificates to trust that web site, you will need to customize your trust store so the HTTPS connection can be successful.

References

  1. http://docs.oracle.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html