4

I am using groovy RESTClient 0.6 to make a POST request. I expect an XML payload in the response. I have the following code:

def restclient = new RESTClient('<some URL>')
def headers= ["Content-Type": "application/xml"]
def body= getClass().getResource("/new_resource.xml").text
/*
 If I omit the closure from the following line of code
 RESTClient blows up with an NPE..BUG?
*/
def response = restclient.post(
                            path:'/myresource', headers:headers, body:body){it}
 println response.status //prints correct response code
 println response.headers['Content-Length']//prints 225
 println response.data //Always null?!

The response.data is always null, even though when I try the same request using Google chrome's postman client, I get back the expected response body. Is this a known issue with RESTClient?

Shawn Sherwood
  • 1,968
  • 2
  • 19
  • 30
The Governor
  • 1,152
  • 1
  • 12
  • 28
  • What is `{it}` while issuing the POST request? – dmahapatro Dec 01 '13 at 09:38
  • @dmahapatro the RESTClient.post method accepts a closure as the last argument. You can send in your code to handle the response in the closure. What's interesting is if you don't use the overload of the post method that accepts the closure, the post method simply blows up. :-( – The Governor Dec 01 '13 at 15:07

2 Answers2

8

The HTTP Builder documentation says that data is supposed to contain the parsed response content but, as you've discovered, it just doesn't. You can, however, get the parsed response content from the reader object. The easiest, most consistent way I've found of doing this is to set the default success and failure closures on your RESTClient object like so:

def restClient = new RESTClient()
restClient.handler.failure = { resp, reader ->
    [response:resp, reader:reader]
}
restClient.handler.success = { resp, reader ->
    [response:resp, reader:reader]
}

You'll get the same thing on success and failure: a Map containing the response (which is an instance of HttpResponseDecorator) and the reader (the type of which will be determined by the content of the response body).

You can then access the response and reader thusly:

def map = restClient.get([:]) // or POST, OPTIONS, etc.
def response = map['response']
def reader = map['reader']

assert response.status == 200
rboy
  • 2,018
  • 1
  • 23
  • 35
Sam T.
  • 497
  • 5
  • 11
1

I faced a similar issue and I took the cue from Sams solution but used closures to address it (similar solution but coded using closures instead of the returned object).

resp.data is always null when using the RESTClient, however the reader contains the data, so it would look something like this:

def restclient = new RESTClient('<some URL>')
def headers= ["Content-Type": "application/xml"]
def body= getClass().getResource("/new_resource.xml").text

try {
    restclient.post(path:'/myresource', headers:headers, body:body) { resp, reader ->
        resp.status // Status Integer
        resp.contentType // Content type String
        resp.headers // Map of headers
        resp.data // <-- ALWAYS null (the bug you faced)
        reader // <-- Data you're looking for
    }
} catch (Exception e) {
    e.response.status // Get HTTP error status Integer
}
rboy
  • 2,018
  • 1
  • 23
  • 35