HTTP Services

Dennis Heimbigner
UCAR/Unidata

Date: July 20, 2011
Revised: December 28, 2015

Table of Contents

  1. Introduction
  2. HTTPSession and Session Semantics
  3. HTTPMethod
  4. HTTPMethodStream
  5. HTTPException
  6. HTTPFactory
  7. ucar.nc2.util.net.HttpClientManager
  8. Appendix A: AuthScope

Introduction

NetCDF-Java clients currently use the Apache HttpClient Libraries for communicating with remote servers to obtain data. Unfortunately, these libraries are under continuous development, so their APIs are unstable from version to version. In addition, as of httpclient version 4.3, the libraries have moved to an immutable object model that makes using them complicated to use.

In order to provide some API stability and to simplify common use, the Apache libraries have been wrapped. The wrapping code is in the ucar.httpservices package. The new public classes are: HTTPFactory.java, HTTPFormBuilder.java, HTTPSession.java, HTTPMethod.java, HTTPMethodStream.java, and HTTPException.java. Additionally, the class ucar.nc2.util.net.HttpClientManager is closely tied to the ucar.httpservices package.

This document describes some of the methods for each class. For a complete description of the API, the javadoc files should be referenced.

Note that when the code was switched to using httpclient version 4.5, the API was changed somewhat to reflect experience with previous versions. Some methods exist to support Backward compatibility, but are deprecated.

HTTPSession and Session Semantics

These class HTTPSession supports a form of session semantics for Java network access. The notion of session is loosely tied to the HTTP notion of session. Specifically, an instance of HTTPSession defines a scope within which authentication and Http methods (e.g. put, get) operate.

The primary key for an HTTPsession object is an instance of AuthScope, which consists of a host (an ip address or name such as unidata.ucar.edu), a port number, and a scheme (e.g. "http" or "https").

Effectively, an AuthScope is intended to map to a specific server somewhere in the internet. Authentication information (credentials) are tied to that scope and all http methods (put, get, etc.) operate in the context of an AuthScope.

Notes:

HTTPSession API

The primary HTTPSession methods of interest are divided into two groups: global and instance. The global methods are static methods of HTTPSession and allow operations that will apply to all instances of HTTPSession, unless specifically overridden. The instance methods, as a rule, parallel the global methods, but apply only to a specific session instance. Some methods can only be specified globally or per-instance.

The non authentication related global methods of general interest are as follows.

The non authentication related per-instance methods of general instance are as follows. The global and per-instance deprecated methods are as follows.

Authentication-Related HTTPSession Methods

The key objects for authentication are the classes org.apache.http.client.CredentialsProvider and org.apache.http.client.Credentials. Basically, when an instance of CrendentialsProvider's getCredentials method is invoked, it is expected to return and instance of Credentials. The two are distinguished because Credentials is immutable, while CredentialsProvider can return a different set of Credentials every time it is invoked.

To see this, consider the case where we want to access a number of datasets on a server, where each dataset might be protected by some combination of username+password. This is often called BASIC authentication. When a request is made for one of these datasets, the CredentialsProvider is invoked and it may do something like pop up a window to ask the user for the needed username+password for this dataset. When another dataset is accessed, it may pop up another window. Thus the same CredentialsProvider may be used repeatedly. In each case, it would return a specific instance of Credentials that contains the requisite username+password for that specific dataset.

HTTPSession supports credentials caching so that if the client repeatedly accesses the same dataset, it will be asked for the username+password only once.

As a rule, it is best to use the methods here that take CredentialsProvider argument. The case of a Credentials argument is only for convenience when only a specific set of credentials is known a-priori.

SSL HTTPSession Methods

SSL support has changed significantly since Apache httpclient 4.5. The following method is exported (public), although using the jvm -D flags (see below) is the preferred method. This method can be used when a client needs to use what is called "client-side" authentication or "mutual" authentication. It is used in conjunction with the "https" scheme. It means that not only does the server provide an authentication certificate to the client, the client must also provide an authentication certificate to the server (thus the term "mutual").

For this case, the client must provide access to a password protected "keystore" in which the client certificate is stored. The first two parameters of the above method specify these.

In addition, the client may wish to use a so-called trust store in which the set of certificates for trusted servers is stored. the last two arguments specify these.

The above method is not strictly necessary since the relevant values can be specified on the java VM command line using the following JVM parameters.

Proxy Support

Proxy support is provided by the following method or (preferably) by the jvm -D flags below. The url string argument specifies how to access the proxy server.

Notes:

The equivalent of the above method can be specified on the java VM command line using the following JVM parameters. This flag is a URL that specifies the proxy.

Miscellaneous -D Flags

It is possible to control the value of certain other session parameters using the following -D flags as arguments to the JVM. These can be set for a client and/or a server.
-D FlagDescription
tds.http.conntimeoutConnection timeout in seconds
tds.http.sotimeoutSocket timeout in seconds

HTTPMethod

This class encapsulates the information about a given method request and response. Its primary operation is execute(), which causes a request to be sent to a server and a response obtained.

An instance of HTTPMethod always operates in the context of a parent HTTPSession object. It is possible to create an HTTPMethod object without specifying a parent session object. In that case, a temporary HTTPSession object is created by the method object. The lifetime of the session object is the same as the method object: that is, when the method object is closed, the temporary session object will also be closed.

HTTPMethod takes a URL string as its primary argument. Optionally (but normally) , it may take an HTTPSession object as an additional argument.

An important point about the URL argument is that it must be compatible with the AuthScope of the parent HTTPSession object. The term "compatible" means the following. The method url is compatible if all of the following are true.

  1. the URL's host+port is the same as the session scope's host+port.
  2. the URL's scheme is compatible with the session scope's scheme, where compatible means either that the two schemes are identical or one is the same as the other with a trailing 's' character removed — so "http" is compatible with "https".

HTTPMethodStream

This class is a subclass of java.io.InputStream. Its purpose is to allow other classes to access the data stream associated with a method response. It is often convenient to get data using an HTTPMethod instance in a Java scope, but then pass the associated input stream out of scope. When the stream is closed (or hits EOF) somewhere else in the code, it is desirable that the associated method and its resources be closed automatically.

HTTPException

This class is a subclass of java.io.IOException. It is the exception for reporting errors out of the ucar.httpservices package.

HTTPFactory

The HTTPFactory class provides the API for obtaining instances of an HTTPSession or HTTPMethod object.

For session creation, the following methods are provided:

The idea is that the argument(s) are sufficient to extract a usable host+port+scheme. The AuthScope argument uses a class specific to the Apache httpclient (core) library.

For method creattion, the supported methods are: GET, HEAD, PUT, POST, and OPTIONS. For each method Xxx, the following factory methods are provided.

As described above, if the session is not explicit, then a temporary session object will be created with the AuthScope taken from the url. Also, if the session is explicit, then the url argument must be compatible with the session's AuthScope.

ucar.nc2.util.net.HttpClientManager

This class is a utility class to perform some specialized actions. Its name begins with "Http" rather than "HTTP" for historical reasons. It has been extensively modified internally to utilize the ucar.httpservices package.

This class contains only static methods and these methods perform the following utility operations.

Examples

Example 1: Create/Use/Release Cycle

This example uses try-with-resources instead of explicit calls to the close methods.
public class Main
{
    public static void main(String[] argv)
    {
	String url = argv[0];
	try (HTTPSession session = new HTTPSession(url);
	     HTTPMethod method = HTTPMethod.Get(session,url);
	     int status = method.execute();
             System.out.printf("Execute: status code = %d\n", status);
	} // implicitly calls method.close() then session.close()
    }
}

Example 2: Using HttpClientManager

public class Main
{
    public static void main(String[] argv)
    {
	String url = argv[0[];
	string content = HttpClientManager.getUrlContentsAsString(url,1024);
    }
}

Example 3: Setting Some Global Parameters

This example set some global parameters and also shows the use of an implicit session.
public class Main
{
    public static void main(String[] argv)
    {
	String url = argv[0];
	String userpwd = argv[1];

	// Set some parameters at the global level
        HTTPSession.setGlobalCredentials(new UsernamePasswordCredentials(userpwd));
	HTTPSession.setGlobalUserAgent("netcdf/java");
	HTTPSession.setMaxConnections(4);
	HTTPSession.setGlobalAuthenticationPreemptive(true);

        try (HTTPMethod method = HTTPMethod.Get(url)) {//implicit session
	    int status = method.execute();
            System.out.printf("Execute: status code = %d\n", status);
	}
    }
}

Example 4: Setting Some Local Parameters

public class Main
{
    public static void main(String[] argv)
    {
	String url = argv[0];
	String userpwd = argv[1];

        try (HTTPSession session = new HTTPSession(url)) {
            session.setCredentials(new UsernamePasswordCredentials(userpwd));
	    session.setUserAgent("agent");
	    session.setConnectionManagerTimeout(475);
	    session.setSoTimeout(475);
	    try (HTTPMethod method = HTTPMethod.Get(session)) {
		int status = method.execute();
		System.out.printf("Execute: status code = %d\n", status);
	    } // method.close()
	} // session.close()
    }
}

Appendices

Appendix A: AuthScope

The AuthScope class is used in a number of places in the ucar.httpservices package. It has a number of constructors, the primary ones are as follows. If the scheme is not explicit then the default scheme (usually "http"). The realm argument should always be AuthScope.ANY_REALM.

Author

Author: Dennis Heimbigner
Affiliation: UCAR/Unidata
email: dmh@ucar.edu