-
Notifications
You must be signed in to change notification settings - Fork 155
Content Types
One of HTTPBuilder's strengths is its in-built ability to parse many content-types. If a response is text/xml it is automatically parsed by groovy.util.XmlSlurper. An application/json response will be parsed into a POGO object via Json-Lib, and a text/plain response will come back as a java.io.Reader. This is done by comparing the response's Content-Type header to entries in the current ParserRegistry instance.
You can see the default content-types handled by HTTPBuilder in the ParserRegistry class}.
If you want to override the automatic parsing (say, to get an XML response as a plain string) you can tell HTTPBuilder how it should try to parse the text. (This is also handy if a server is being dumb and serving HTML data as plain text, for instance.)
The contentType parameter tells HTTPBuilder how it should parse the response.
def http = new HTTPBuilder('http://ajax.googleapis.com')
http.request( Method.GET, ContentType.TEXT ) { req ->
uri.path = '/ajax/services/search/web'
uri.query = [ v:'1.0', q: 'Calvin and Hobbes' ]
headers.Accept = 'application/json'
response.success = { resp, reader ->
println "Got response: ${resp.statusLine}"
println "Content-Type: ${resp.headers.'Content-Type'}"
print reader.text
}
}
The contentType parameter also instructs HTTPBuilder to add an Accept header to the request for the specified content-type. Assuming we still want to get JSON data, but not parse it, the headers.Accept = ... line above overrides the automatic Accept: text/plain header that would otherwise be added by the ContentType.TEXT argument.
Now assume we always want to handle XML as plain text. (maybe you're passing it on to a SAX parser or something similar.) We can re-use the TEXT content-type handler by assigning it to the XML content-type in the ParserRegistry:
http.parser.'application/xml' = http.parser.'text/plain'
Now, any response that comes in with a Content-Type: application/xml header will be handled using the plain-text parser -- meaning it's simply returned as a reader.
To add parsing for new content types, simply add a new entry to the builder's ParserRegistry. For example, to parse comma-separated-values using OpenCSV:
import au.com.bytecode.opencsv.CSVReader
import groovyx.net.http.ParserRegistry
http.parser.'text/csv' = { resp ->
return new CSVReader( new InputStreamReader( resp.entity.content,
ParserRegistry.getCharset( resp ) ) )
}
A CSVReader instance will then be passed as the second argument to the response handler:
http.get( uri : 'http://somehost.com/contacts.csv',
contentType : 'text/csv' ) { resp, csv ->
assert csv instanceof CSVReader
// parse the csv stream here.
}
You can refer to IANA for a complete list of registered content-type names, but the most common are already handled in the ContentType enumeration.