The URIBuilder class is extremely useful for URI and URL construction and manipulation. It is used within HTTPBuilder, but it is also useful even from plain Java code.

If you've ever attempted to change a URL relative to its current path, you've probably noticed that using URI.resolvePath(..) strips off everything after the last '/' of the URI, including any 'document,' query string and fragment. URIBuilder aims to make URI manipulation a lot easier and allows you to manipulate aspects of the URL while maintaining the other pieces:

import groovyx.net.http.URIBuilder

def uri = new URIBuilder( 'http://www.google.com/one/two?a=1#frag' )

uri.scheme = 'https'
assert uri.toString() == 'https://www.google.com:80/one/two?a=1#frag'

uri.host = 'localhost'
assert uri.toString() == 'https://localhost:80/one/two?a=1#frag'

uri.port = 8080
assert uri.toString() == 'https://localhost:8080/one/two?a=1#frag'

uri.fragment = 'asdf2'
assert uri.toString() == 'https://localhost:8080/one/two?a=1#asdf2'

// relative paths:
uri.path = 'three/four.html'
assert uri.toString() == 'https://localhost:8080/one/three/four.html?a=1#asdf2'

uri.path = '../four/five'
assert uri.toString() == 'https://localhost:8080/one/four/five?a=1#asdf2'

// control the entire path with leading '/' :
uri.path = '/six'
assert uri.toString() == 'https://localhost:8080/six?a=1#asdf2'

Query parameters can also be easily manipulated as a map:

def uri = new groovyx.net.http.URIBuilder( 'http://localhost?a=1&b=2' )
assert uri.query instanceof Map
assert uri.query.a == '1'
assert uri.query.b == '2'

uri.addQueryParam 'd', '4'
uri.removeQueryParam 'b'

assert uri.toString() == 'http://localhost?d=4&a=1'

uri.query = [z:0,y:9,x:8]
assert uri.toString() == 'http://localhost?z=0&y=9&x=8'

uri.query = null
assert uri.toString() == 'http://localhost'


// parameters are also properly escaped as well:

uri.query = [q:'a:b',z:'war & peace']
assert uri.toString() == 'http://localhost?q=a%3Ab&z=war+%26+peace'

As mentioned above, URIBuilder is also useful from Java. This is because URIBuilder's setter methods return the modified builder instance, to allow for the 'fluent interface' pattern. The above example could be written in Java as follows:

URIBuilder uri = new URIBuilder( "http://www.google.com/one/two?a=1#frag" );

uri.setScheme( "https" ).setHost( "localhost" ).setPath( "../three" );
assert uri.toString().equals( "https://localhost/three?a=1#frag" );

URIBuilder also has methods for coercion to a URI or URL instance. Since URIBuilder is mutable, it generally should not be used for things like map keys. In this case, the builder's current state should be frozen by coercing it to a URI or URL.