Introduction

HTTPBuilder is optimized for three tasks:

  1. Streaming response handling,
  2. Automatic response parsing based on content-type
  3. Sucess & failure handling based on the response status code

To achieve this, HTTPBuilder exposes convenience methods for common request types, (i.e. GET and POST) and a more complex request method that allows fine-grained configuration of each request and response.

The following example shows most of the request method's features.

import groovyx.net.http.HTTPBuilder
import static groovyx.net.http.Method.GET
import static groovyx.net.http.ContentType.TEXT

// initialze a new builder and give a default URL
def http = new HTTPBuilder( 'http://www.google.com/search' )

http.request(GET,TEXT) { req ->
  uri.path = '/mail/help/tasks/' // overrides any path in the default URL
  headers.'User-Agent' = 'Mozilla/5.0'

  response.success = { resp, reader ->
    assert resp.status == 200
    println "My response handler got response: ${resp.statusLine}"
    println "Response length: ${resp.headers.'Content-Length'}"
    System.out << reader // print response reader
  }

  // called only for a 404 (not found) status code:
  response.'404' = { resp ->
    println 'Not found'
  }
}

If you are familiar with the HTTP protocol, most of the above should be self-explanatory. The request() method accepts three parameters: a method, content-type, and a request configuration closure. Within the configuration closure, we can fine-tune the parameters for this request, including manipulating portions of the URL, and adding request headers. A full list of properties that can be manipulated during request configuration can be found in the RequestConfigDelegate class.

The req parameter passed to the closure is an HttpRequest instance, which can be used to configure additional aspects of the request for which HTTPBuilder does not provide a wrapper.

The remaining 'response' definitions in the above example configure how the response is handled based on the HTTP status code returned by the server. In general, a "success" and "failure" response handler may be defined, or a response handler may be defined for a specific response code.

In the simplest case, no 'failure' handler needs to be defined; the default failure handler will throw an exception, which is triggered for any response code > 399. You can also customize default response handlers that will be in effect for all requests made by the HTTPBuilder instance:

http.handler.'401' = { resp ->
  println "Access denied"
}

// Used for all other failure codes not handled by a code-specific handler:
http.handler.failure = { resp ->
  println "Unexpected failure: ${resp.statusLine}"
}

The Magic: Built-in Content-Type Parsing

HTTPBuilder is also able to intelligently handle different response content-types. In this example, the response data is automatically parsed into a JSON object, which is then passed to the 'success' response handler.

import groovyx.net.http.HTTPBuilder
import static groovyx.net.http.Method.GET
import static groovyx.net.http.ContentType.JSON

def http = new HTTPBuilder( 'http://ajax.googleapis.com' )
http.request( GET, JSON ) {
  uri.path = '/ajax/services/search/web'
  uri.query = [ v:'1.0', q: 'Calvin and Hobbes' ]

  response.success = { resp, json ->
    assert json.size() == 3
    println "Query response: "
    json.responseData.results.each {
      println "  ${it.titleNoFormatting} : ${it.visibleUrl}"
    }
  }
}

You can try the above example by adding the @Grab macro (as demonstrated on the download page) with Groovy 1.6.

Parser Resolution

By default, new HTTPBuilder instances use ContentType.ANY as the initial content-type. This means every request has an Accept: */* header, and it is up to the server to decide what appropriate content-type to return. HTTPBuilder then chooses the appropriate parser from its ParserRegistry based on the response Content-Type header value.

If a contentType is set (either in HTTPBuilder.setContentType(...) or as a request method parameter), HTTPBuilder will attempt to parse the response using that content-type, regardless of what the server actually responds with. The first example on this page actually uses that strategy to parse an HTML document as plain text (i.e. by creating a Reader) rather than detecting an HTML content-type and using the default HTML parsing method. You can read more about automatic content-type parsing on the Content Types page.

Logging and Debugging

Probably the quickest way to debug is to turn on logging for HTTPBuilder and Apache HttpClient. An example log4j configuration can be used to output headers and request/response content, as well as additional information on what HTTPBuilder is doing with the request and response.

To see the raw request and response output, change the Apache HttpClient logging parameters to DEBUG like so:

    <category name="org.apache.http.headers">
        <priority value="DEBUG" />
    </category>
    <category name="org.apache.http.wire">
        <priority value="DEBUG" />
    </category>