Class HTTPBuilder

java.lang.Object
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 invalid input: '<'invalid input: '<' 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 invalid input: '<'invalid input: '<' 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}"
       }
     }
   }
 
  • Field Details

    • client

      private org.apache.http.client.HttpClient 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 Details

    • 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 Details

    • 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:
    • 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:
    • 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

      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

      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

      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:
    • 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 HTTPBuilder.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:
    • 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:
    • 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 invalid input: '&' 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.client.HttpClient getClient()
      Return the underlying HTTPClient that is used to handle HTTP requests.
      Returns:
      the client instance.
    • setClient

      public void setClient(org.apache.http.client.HttpClient client)
    • createClient

      protected org.apache.http.client.HttpClient createClient(org.apache.http.params.HttpParams params)
      Override this method in a subclass to customize creation of the HttpClient instance.
      Parameters:
      params -
      Returns:
    • 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(String, int, String)
    • ignoreSSLIssues

      Ignores certificate issues for SSL connections. Cert does not have to be from a trusted authority and the hostname does not need to be verified. This is primarily for dev situations that make use of localhost, build, and test servers.
      Throws:
      KeyStoreException
      NoSuchAlgorithmException
      UnrecoverableKeyException
      KeyManagementException
    • shutdown

      public void shutdown()
      Release any system resources held by this instance.
      See Also:
      • ClientConnectionManager.shutdown()