groovyx.net.http
Class HTTPBuilder

java.lang.Object
  extended by groovyx.net.http.HTTPBuilder
Direct Known Subclasses:
AsyncHTTPBuilder, RESTClient

public class HTTPBuilder
extends Object

Groovy DSL for easily making HTTP requests, and handling request and response data. This class adds a number of convenience mechanisms built on top of Apache HTTPClient for things like URL-encoded POSTs and REST requests that require building and parsing JSON or XML. Convenient access to a few common authentication methods is also available.

Conventions

HTTPBuilder has properties for default headers, URI, contentType, etc. All of these values are also assignable (and in many cases, in much finer detail) from the HTTPBuilder.RequestConfigDelegate as well. In any cases where the value is not set on the delegate (from within a request closure,) the builder's default value is used.

For instance, any methods that do not take a uri parameter assume you will set the uri property in the request closure or use HTTPBuilder's assigned default URI.

Response Parsing

By default, HTTPBuilder uses ContentType.ANY as the default content-type. This means the value of the request's Accept header is */*, and the response parser is determined based on the response content-type header.

If any contentType is given (either in setContentType(Object) or as a request method parameter), the builder will attempt to parse the response using that content-type, regardless of what the server actually responds with.

Examples:

Perform an HTTP GET and print the response:
   def http = new HTTPBuilder('http://www.google.com')

   http.get( path : '/search',
             contentType : TEXT,
             query : [q:'Groovy'] ) { resp, reader ->
     println "response status: ${resp.statusLine}"
     println 'Response data: -----'
     System.out << reader
     println '\n--------------------'
   }
 
Long form for other HTTP methods, and response-code-specific handlers. This is roughly equivalent to the above example.
   def http = new HTTPBuilder('http://www.google.com/search?q=groovy')

   http.request( GET, TEXT ) { req ->

     // executed for all successful responses:
     response.success = { resp, reader ->
       println 'my response handler!'
       assert resp.statusLine.statusCode == 200
       println resp.statusLine
       System.out << reader // print response stream
     }

     // executed only if the response status code is 401:
     response.'404' = { resp ->
       println 'not found!'
     }
   }
 
You can also set a default response handler called for any status code > 399 that is not matched to a specific handler. Setting the value outside a request closure means it will apply to all future requests with this HTTPBuilder instance:
   http.handler.failure = { resp ->
     println "Unexpected failure: ${resp.statusLine}"
   }
 
And... Automatic response parsing for registered content types!
   http.request( 'http://ajax.googleapis.com', 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}"
       }
     }
   }
 

Author:
Tom Nichols

Nested Class Summary
protected  class HTTPBuilder.RequestConfigDelegate
          Encloses all properties and method calls used within the request(Object, Method, Object, Closure) 'config' closure argument.
 
Field Summary
protected  AuthConfig auth
           
protected  boolean autoAcceptHeader
           
protected  org.apache.http.impl.client.AbstractHttpClient client
           
protected  ContentEncodingRegistry contentEncodingHandler
           
protected  Object defaultContentType
           
protected  Object defaultRequestContentType
           
protected  Map<Object,Object> defaultRequestHeaders
           
protected  Map<Object,groovy.lang.Closure> defaultResponseHandlers
           
protected  URIBuilder defaultURI
           
protected  EncoderRegistry encoders
           
protected  org.apache.commons.logging.Log log
           
protected  ParserRegistry parsers
           
 
Constructor Summary
HTTPBuilder()
          Creates a new instance with a null default URI.
HTTPBuilder(Object defaultURI)
          Give a default URI to be used for all request methods that don't explicitly take a URI parameter.
HTTPBuilder(Object defaultURI, Object defaultContentType)
          Give a default URI to be used for all request methods that don't explicitly take a URI parameter, and a default content-type to be used for request encoding and response parsing.
 
Method Summary
protected  Map<Object,groovy.lang.Closure> buildDefaultResponseHandlers()
          Creates default response handlers for success and failure status codes.
protected  org.apache.http.impl.client.AbstractHttpClient createClient(org.apache.http.params.HttpParams params)
          Override this method in a subclass to customize creation of the HttpClient instance.
protected  void defaultFailureHandler(HttpResponseDecorator resp)
          This is the default response.failure handler.
protected  Object defaultSuccessHandler(HttpResponseDecorator resp, Object parsedData)
          This is the default response.success handler.
protected  Object doRequest(HTTPBuilder.RequestConfigDelegate delegate)
          All request methods delegate to this method.
protected  Object doRequest(URI uri, Method method, Object contentType, groovy.lang.Closure configClosure)
          Create a HTTPBuilder.RequestConfigDelegate from the given arguments, execute the config closure, then pass the delegate to doRequest(RequestConfigDelegate), which actually executes the request.
 Object get(Map<String,?> args)
          Convenience method to perform an HTTP GET.
 Object get(Map<String,?> args, groovy.lang.Closure responseClosure)
          Convenience method to perform an HTTP GET.
 AuthConfig getAuth()
          Used to access the AuthConfig handler used to configure common authentication mechanism.
 org.apache.http.impl.client.AbstractHttpClient getClient()
          Return the underlying HTTPClient that is used to handle HTTP requests.
 Object getContentType()
           
 EncoderRegistry getEncoder()
          Retrieve the map of registered request content-type encoders.
 Map<?,groovy.lang.Closure> getHandler()
          Retrieve the map of response code handlers.
 Map<?,?> getHeaders()
          Get the map of default headers that will be added to all requests.
 ParserRegistry getParser()
          Retrieve the map of registered response content-type parsers.
 Object getUri()
          Get the default URI used for requests that do not explicitly take a uri param.
 boolean isAutoAcceptHeader()
          Indicates whether or not this client should automatically send an Accept header based on the contentType property.
protected  Object parseResponse(org.apache.http.HttpResponse resp, Object contentType)
          Parse the response data based on the given content-type.
 Object post(Map<String,?> args)
          Convenience method to perform an HTTP POST.
 Object post(Map<String,?> args, groovy.lang.Closure responseClosure)
           Convenience method to perform an HTTP form POST.
 Object request(Method method, groovy.lang.Closure configClosure)
          Make an HTTP request to the default URI, and parse using the default content-type.
 Object request(Method method, Object contentType, groovy.lang.Closure configClosure)
          Make an HTTP request using the default URI, with the given method, content-type, and configuration.
 Object request(Object uri, Method method, Object contentType, groovy.lang.Closure configClosure)
          Make a request for the given HTTP method and content-type, with additional options configured in the configClosure.
 void setAuthConfig(AuthConfig ac)
          Set an alternative AuthConfig implementation to handle authorization.
 void setAutoAcceptHeader(boolean shouldSendAcceptHeader)
          Indicate whether or not this cliernt should send an Accept header automatically based on the contentType property.
 void setContentEncoding(Object... encodings)
          Set acceptable request and response content-encodings.
 void setContentEncodingRegistry(ContentEncodingRegistry cer)
          Set a custom registry used to handle different content-encoding types in responses.
 void setContentType(Object ct)
          Set the default content type that will be used to select the appropriate request encoder and response parser.
 void setEncoderRegistry(EncoderRegistry er)
          Set a custom registry used to handle different request content-types.
 void setHeaders(Map<?,?> headers)
          Set the default headers to add to all requests made by this builder instance.
 void setParserRegistry(ParserRegistry pr)
          Set a custom registry used to handle different response content-types
 void setProxy(String host, int port, String scheme)
          Set the default HTTP proxy to be used for all requests.
 void setUri(Object uri)
          Set the default URI used for requests that do not explicitly take a uri param.
 void shutdown()
          Release any system resources held by this instance.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

client

protected org.apache.http.impl.client.AbstractHttpClient client

defaultURI

protected URIBuilder defaultURI

auth

protected AuthConfig auth

log

protected final org.apache.commons.logging.Log log

defaultContentType

protected Object defaultContentType

defaultRequestContentType

protected Object defaultRequestContentType

autoAcceptHeader

protected boolean autoAcceptHeader

defaultResponseHandlers

protected final Map<Object,groovy.lang.Closure> defaultResponseHandlers

contentEncodingHandler

protected ContentEncodingRegistry contentEncodingHandler

defaultRequestHeaders

protected final Map<Object,Object> defaultRequestHeaders

encoders

protected EncoderRegistry encoders

parsers

protected ParserRegistry parsers
Constructor Detail

HTTPBuilder

public HTTPBuilder()
Creates a new instance with a null default URI.


HTTPBuilder

public HTTPBuilder(Object defaultURI)
            throws URISyntaxException
Give a default URI to be used for all request methods that don't explicitly take a URI parameter.

Parameters:
defaultURI - either a URL, URI or object whose toString() produces a valid URI string. See URIBuilder.convertToURI(Object).
Throws:
URISyntaxException - if the given argument does not represent a valid URI

HTTPBuilder

public HTTPBuilder(Object defaultURI,
                   Object defaultContentType)
            throws URISyntaxException
Give a default URI to be used for all request methods that don't explicitly take a URI parameter, and a default content-type to be used for request encoding and response parsing.

Parameters:
defaultURI - either a URL, URI or object whose toString() produces a valid URI string. See URIBuilder.convertToURI(Object).
defaultContentType - content-type string. See ContentType for common types.
Throws:
URISyntaxException - if the uri argument does not represent a valid URI
Method Detail

createClient

protected org.apache.http.impl.client.AbstractHttpClient createClient(org.apache.http.params.HttpParams params)
Override this method in a subclass to customize creation of the HttpClient instance.

Parameters:
params -
Returns:

get

public Object get(Map<String,?> args)
           throws org.apache.http.client.ClientProtocolException,
                  IOException,
                  URISyntaxException

Convenience method to perform an HTTP GET. It will use the HTTPBuilder's registered response handlers to handle success or failure status codes. By default, the success response handler will attempt to parse the data and simply return the parsed object.

Note: If using the default success response handler, be sure to read the caveat regarding streaming response data.

Parameters:
args - see HTTPBuilder.RequestConfigDelegate.setPropertiesFromMap(Map)
Returns:
whatever was returned from the response closure.
Throws:
URISyntaxException - if a uri argument is given which does not represent a valid URI
IOException
org.apache.http.client.ClientProtocolException
See Also:
getHandler(), defaultSuccessHandler(HttpResponseDecorator, Object), defaultFailureHandler(HttpResponseDecorator)

get

public Object get(Map<String,?> args,
                  groovy.lang.Closure responseClosure)
           throws org.apache.http.client.ClientProtocolException,
                  IOException,
                  URISyntaxException

Convenience method to perform an HTTP GET. The response closure will be called only on a successful response.

A 'failed' response (i.e. any HTTP status code > 399) will be handled by the registered 'failure' handler. The default failure handler throws an HttpResponseException.

Parameters:
args - see HTTPBuilder.RequestConfigDelegate.setPropertiesFromMap(Map)
responseClosure - code to handle a successful HTTP response
Returns:
any value returned by the response closure.
Throws:
org.apache.http.client.ClientProtocolException
IOException
URISyntaxException - if a uri argument is given which does not represent a valid URI

post

public Object post(Map<String,?> args)
            throws org.apache.http.client.ClientProtocolException,
                   URISyntaxException,
                   IOException

Convenience method to perform an HTTP POST. It will use the HTTPBuilder's registered response handlers to handle success or failure status codes. By default, the success response handler will attempt to parse the data and simply return the parsed object.

Note: If using the default success response handler, be sure to read the caveat regarding streaming response data.

Parameters:
args - see HTTPBuilder.RequestConfigDelegate.setPropertiesFromMap(Map)
Returns:
whatever was returned from the response closure.
Throws:
IOException
URISyntaxException - if a uri argument is given which does not represent a valid URI
org.apache.http.client.ClientProtocolException
See Also:
getHandler(), defaultSuccessHandler(HttpResponseDecorator, Object), defaultFailureHandler(HttpResponseDecorator)

post

public Object post(Map<String,?> args,
                   groovy.lang.Closure responseClosure)
            throws URISyntaxException,
                   org.apache.http.client.ClientProtocolException,
                   IOException

Convenience method to perform an HTTP form POST. The response closure will be called only on a successful response.

A 'failed' response (i.e. any HTTP status code > 399) will be handled by the registered 'failure' handler. The default failure handler throws an HttpResponseException.

The request body (specified by a body named parameter) will be converted to a url-encoded form string unless a different requestContentType named parameter is passed to this method. (See EncoderRegistry.encodeForm(Map).)

Parameters:
args - see HTTPBuilder.RequestConfigDelegate.setPropertiesFromMap(Map)
responseClosure - code to handle a successful HTTP response
Returns:
any value returned by the response closure.
Throws:
org.apache.http.client.ClientProtocolException
IOException
URISyntaxException - if a uri argument is given which does not represent a valid URI

request

public Object request(Method method,
                      groovy.lang.Closure configClosure)
               throws org.apache.http.client.ClientProtocolException,
                      IOException
Make an HTTP request to the default URI, and parse using the default content-type.

Parameters:
method - HTTP method
configClosure - request configuration options
Returns:
whatever value was returned by the executed response handler.
Throws:
org.apache.http.client.ClientProtocolException
IOException
See Also:
request(Object, Method, Object, Closure)

request

public Object request(Method method,
                      Object contentType,
                      groovy.lang.Closure configClosure)
               throws org.apache.http.client.ClientProtocolException,
                      IOException
Make an HTTP request using the default URI, with the given method, content-type, and configuration.

Parameters:
method - HTTP method
contentType - either a ContentType or valid content-type string.
configClosure - request configuration options
Returns:
whatever value was returned by the executed response handler.
Throws:
org.apache.http.client.ClientProtocolException
IOException
See Also:
request(Object, Method, Object, Closure)

request

public Object request(Object uri,
                      Method method,
                      Object contentType,
                      groovy.lang.Closure configClosure)
               throws org.apache.http.client.ClientProtocolException,
                      IOException,
                      URISyntaxException
Make a request for the given HTTP method and content-type, with additional options configured in the configClosure. See HTTPBuilder.RequestConfigDelegate for options.

Parameters:
uri - either a URL, URI or object whose toString() produces a valid URI string. See URIBuilder.convertToURI(Object).
method - HTTP method
contentType - either a ContentType or valid content-type string.
configClosure - closure from which to configure options like uri.path, request parameters, headers, request body and response handlers.
Returns:
whatever value was returned by the executed response handler.
Throws:
org.apache.http.client.ClientProtocolException
IOException
URISyntaxException - if the uri argument does not represent a valid URI

doRequest

protected Object doRequest(URI uri,
                           Method method,
                           Object contentType,
                           groovy.lang.Closure configClosure)
                    throws org.apache.http.client.ClientProtocolException,
                           IOException
Create a HTTPBuilder.RequestConfigDelegate from the given arguments, execute the config closure, then pass the delegate to doRequest(RequestConfigDelegate), which actually executes the request.

Throws:
org.apache.http.client.ClientProtocolException
IOException

doRequest

protected Object doRequest(HTTPBuilder.RequestConfigDelegate delegate)
                    throws org.apache.http.client.ClientProtocolException,
                           IOException
All request methods delegate to this method.

Throws:
org.apache.http.client.ClientProtocolException
IOException

parseResponse

protected Object parseResponse(org.apache.http.HttpResponse resp,
                               Object contentType)
                        throws HttpResponseException
Parse the response data based on the given content-type. If the given content-type is ContentType.ANY, the content-type header from the response will be used to determine how to parse the response.

Parameters:
resp -
contentType -
Returns:
whatever was returned from the parser retrieved for the given content-type, or null if no parser could be found for this content-type. The parser will also return null if the response does not contain any content (e.g. in response to a HEAD request).
Throws:
HttpResponseException - if there is a error parsing the response

buildDefaultResponseHandlers

protected Map<Object,groovy.lang.Closure> buildDefaultResponseHandlers()
Creates default response handlers for success and failure status codes. This is used to populate the handler map when a new HTTPBuilder instance is created.

Returns:
the default response handler map.
See Also:
defaultSuccessHandler(HttpResponseDecorator, Object), defaultFailureHandler(HttpResponseDecorator)

defaultSuccessHandler

protected Object defaultSuccessHandler(HttpResponseDecorator resp,
                                       Object parsedData)
                                throws ResponseParseException

This is the default response.success handler. It will be executed if the response is not handled by a status-code-specific handler (i.e. response.'200'= {..}) and no generic 'success' handler is given (i.e. response.success = {..}.) This handler simply returns the parsed data from the response body. In most cases you will probably want to define a response.success = {...} handler from the request closure, which will replace the response handler defined by this method.

Note for parsers that return streaming content:

For responses parsed as BINARY or TEXT, the parser will return streaming content -- an InputStream or Reader. In these cases, this handler will buffer the the response content before the network connection is closed.

In practice, a user-supplied response handler closure is designed to handle streaming content so it can be read directly from the response stream without buffering, which will be much more efficient. Therefore, it is recommended that request method variants be used which explicitly accept a response handler closure in these cases.

Parameters:
resp - HTTP response
parsedData - parsed data as resolved from this instance's ParserRegistry
Returns:
the parsed data object (whatever the parser returns).
Throws:
ResponseParseException - if there is an error buffering a streaming response.

defaultFailureHandler

protected void defaultFailureHandler(HttpResponseDecorator resp)
                              throws HttpResponseException
This is the default response.failure handler. It will be executed if no status-code-specific handler is set (i.e. response.'404'= {..}). This default handler will throw a HttpResponseException when executed. In most cases you will want to define your own response.failure = {...} handler from the request closure, if you don't want an exception to be thrown for 4xx and 5xx status responses.

Parameters:
resp -
Throws:
HttpResponseException

getHandler

public Map<?,groovy.lang.Closure> getHandler()
Retrieve the map of response code handlers. Each map key is a response code as a string (i.e. '401') or either 'success' or 'failure'. Use this to set default response handlers, e.g.
builder.handler.'401' = { resp -> println "${resp.statusLine}" }

Returns:
See Also:
Status

getParser

public ParserRegistry getParser()
Retrieve the map of registered response content-type parsers. Use this to set default response parsers, e.g.
 builder.parser.'text/javascript' = { resp ->
    return resp.entity.content // just returns an InputStream
 }

Returns:

getEncoder

public EncoderRegistry getEncoder()
Retrieve the map of registered request content-type encoders. Use this to customize a request encoder for specific content-types, e.g.
 builder.encoder.'text/javascript' = { body ->
   def json = body.call( new JsonGroovyBuilder() )
   return new StringEntity( json.toString() )
 }
By default this map is populated by calling EncoderRegistry.buildDefaultEncoderMap(). This method is also used by HTTPBuilder.RequestConfigDelegate to retrieve the proper encoder for building the request content body.

Returns:
a map of 'encoder' closures, keyed by content-type string.

setContentType

public void setContentType(Object ct)
Set the default content type that will be used to select the appropriate request encoder and response parser. The ContentType enum holds some common content-types that may be used, i.e.
 import static ContentType.*
 builder.contentType = XML
 
Setting the default content-type does three things:
  1. It tells the builder to encode any request body as this content-type. Calling RequestConfigDelegate#setRequestContentType(String) can override this on a per-request basis.
  2. Tells the builder to parse any response as this content-type, regardless of any content-type header that is sent in the response.
  3. Sets the Accept header to this content-type for all requests (see ContentType.getAcceptHeader()). Note that any Accept header explicitly set either in setHeaders(Map) or HTTPBuilder.RequestConfigDelegate.setHeaders(Map) will override this value.

Additionally, if the content-type is set to ContentType.ANY, HTTPBuilder will rely on the content-type response header to determine how to parse the response data. This allows the user to rely on response headers if they are accurate, or ignore them and forcibly use a certain response parser if so desired.

This value is a default and may always be overridden on a per-request basis by using the builder.request( Method, ContentType, Closure ) method or passing a contentType named parameter.

Parameters:
ct - either a ContentType or string value (i.e. "text/xml".)
See Also:
EncoderRegistry, ParserRegistry

getContentType

public Object getContentType()
Returns:
default content type used for request and response.

setAutoAcceptHeader

public void setAutoAcceptHeader(boolean shouldSendAcceptHeader)
Indicate whether or not this cliernt should send an Accept header automatically based on the contentType property.

Parameters:
shouldSendAcceptHeader - true if the client should automatically insert an Accept header, otherwise false.

isAutoAcceptHeader

public boolean isAutoAcceptHeader()
Indicates whether or not this client should automatically send an Accept header based on the contentType property. Default is true.

Returns:
true if the client should automatically add an Accept header to the request; if false, no header is added.

setContentEncoding

public void setContentEncoding(Object... encodings)
Set acceptable request and response content-encodings.

Parameters:
encodings - each Object should be either a ContentEncoding.Type value, or a content-encoding string that is known by the ContentEncodingRegistry
See Also:
ContentEncodingRegistry

setUri

public void setUri(Object uri)
            throws URISyntaxException
Set the default URI used for requests that do not explicitly take a uri param.

Parameters:
uri - either a URL, URI or object whose toString() produces a valid URI string. See URIBuilder.convertToURI(Object).
Throws:
URISyntaxException - if the uri argument does not represent a valid URI

getUri

public Object getUri()
Get the default URI used for requests that do not explicitly take a uri param.

Returns:
a URIBuilder instance. Note that the return type is Object simply so that it matches with its JavaBean setUri(Object) counterpart.

setHeaders

public void setHeaders(Map<?,?> headers)
Set the default headers to add to all requests made by this builder instance. These values will replace any previously set default headers.

Parameters:
headers - map of header names & values.

getHeaders

public Map<?,?> getHeaders()
Get the map of default headers that will be added to all requests. This is a 'live' collection so it may be used to add or remove default values.

Returns:
the map of default header names and values.

getClient

public org.apache.http.impl.client.AbstractHttpClient getClient()
Return the underlying HTTPClient that is used to handle HTTP requests.

Returns:
the client instance.

getAuth

public AuthConfig getAuth()
Used to access the AuthConfig handler used to configure common authentication mechanism. Example:
builder.auth.basic( 'myUser', 'somePassword' )

Returns:

setAuthConfig

public void setAuthConfig(AuthConfig ac)
Set an alternative AuthConfig implementation to handle authorization.

Parameters:
ac - instance to use.

setEncoderRegistry

public void setEncoderRegistry(EncoderRegistry er)
Set a custom registry used to handle different request content-types.

Parameters:
er -

setParserRegistry

public void setParserRegistry(ParserRegistry pr)
Set a custom registry used to handle different response content-types

Parameters:
pr -

setContentEncodingRegistry

public void setContentEncodingRegistry(ContentEncodingRegistry cer)
Set a custom registry used to handle different content-encoding types in responses.

Parameters:
cer -

setProxy

public void setProxy(String host,
                     int port,
                     String scheme)
Set the default HTTP proxy to be used for all requests.

Parameters:
host - host name or IP
port - port, or -1 for the default port
scheme - usually "http" or "https," or null for the default
See Also:
HttpHost.HttpHost(String, int, String)

shutdown

public void shutdown()
Release any system resources held by this instance.

See Also:
ClientConnectionManager.shutdown()


Copyright © 2008-2012. All Rights Reserved.