Pluggable HTTP Transport

The HTTP library has a fully pluggable HTTP transport layer that allows you to build on top of the low-level HTTP of your choice and optimize for the Java platform your application is running on.

Thanks to this abstraction, code written for one platform will automatically work across all supported platforms, from mobile applications such as those built for Android, to installed applications, to web applications such as those built on Google App Engine. The HTTP library provides high-level functionality that is compatible across of those platforms, but at the same time takes advantage of lower-level functionality when necessary.

Contents

Choosing a low-level HTTP transport library

A big advantage of the HTTP library is that the choice of low-level HTTP transport library is fully pluggable. There are three built-in choices:

Logging

We use java.util.logging.Logger for logging HTTP request and response details, including URL, headers, and content.

Normally logging is managed using a logging.properties file. For example:

# Properties file which configures the operation of the JDK logging facility.
# The system will look for this config file to be specified as a system property:
# -Djava.util.logging.config.file=${project_loc:googleplus-simple-cmdline-sample}/logging.properties

# Set up the console handler (uncomment "level" to show more fine-grained messages)
handlers = java.util.logging.ConsoleHandler
java.util.logging.ConsoleHandler.level = CONFIG

# Set up logging of HTTP requests and responses (uncomment "level" to show)
com.google.api.client.http.level = CONFIG

Here we use ConsoleHandler. Another popular choice is FileHandler.

Example for enabling logging in code:

import com.google.api.client.http.HttpTransport;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;

public static void enableLogging() {
  Logger logger = Logger.getLogger(HttpTransport.class.getName());
  logger.setLevel(Level.CONFIG);
  logger.addHandler(new Handler() {

    @Override
    public void close() throws SecurityException {
    }

    @Override
    public void flush() {
    }

    @Override
    public void publish(LogRecord record) {
      // default ConsoleHandler will print >= INFO to System.err
      if (record.getLevel().intValue() < Level.INFO.intValue()) {
        System.out.println(record.getMessage());
      }
    }
  });
}

Handling HTTP error responses

When an HTTP error response (an HTTP status code of 300 or higher) is received, HttpRequest.execute() will throw an HttpResponseException. Here's an example usage:

try {
  request.execute()
} catch (HttpResponseException e) {
  System.err.println(e.getStatusMessage());
}

If you need to intercept error responses, it may be handy to use the HttpUnsuccessfulResponseHandler. Example usage:

public static class MyInitializer implements HttpRequestInitializer, HttpUnsuccessfulResponseHandler {

  @Override
  public boolean handleResponse(
      HttpRequest request, HttpResponse response, boolean retrySupported) throws IOException {
    System.out.println(response.getStatusCode() + " " + response.getStatusMessage());
    return false;
  }

  @Override
  public void initialize(HttpRequest request) throws IOException {
    request.setUnsuccessfulResponseHandler(this);
  }
}

...

HttpRequestFactory requestFactory = transport.createRequestFactory(new MyInitializer());