Search code examples
androidretrofitrobospice

Retrofit: Get original response body when request fails


I am using Retrofit (1.6.1) with Robospice (1.4.14) to get data from some services (response should be in JSON).

In some cases, I might receive a HTML error page instead of a JSON response. The server returns a 200 status code, and I can not change that. In such cases, RoboSpice will call the onRequestFailure(SpiceException) method.

There, I am able to get the original RetrofitError excpetion, but the body is null. This is how I get it:

if (spiceException.getCause() instanceof RetrofitError) {
    RetrofitError error = (RetrofitError) spiceException.getCause();
    error.getBody(); // returns null
}

After investigating the source code of Retrofit, I found out that the body is replaced with null if the conversion fails (which is the case here, as Retrofit expect JSON and receives HTML).

The following line in RestAdapter is the source of my issue:

response = Utils.replaceResponseBody(response, null);

Is there a way to not set the body to null? In an other SO question, I found that if the server returns 4xx, the body is kept, but I can not change that.


Solution

  • You should probably create a retrofitted method that will just return a retrofit.client.Response and manually call conversion on it if the response body is in the necessary format.

    Your Retrofit interface:

    ...
    @GET("/foo/bar")
    Response fooBarMethod(Object foo, Object bar);
    ...
    

    Your RoboSpice request:

    ...
    @Override
    public final FooBar loadDataFromNetwork() throws Exception {
        Response r = getService().fooBarMethod(foo, bar);
        if (isBodyInHtmlFormat()) {
            // cool stuff
            throw new ResponseIsHtmlException();
        } else {
            // it is wise to make sure that it is 
            // exactly the same converter you are passing to
            // your RetrofitSpiceService
            Converter converter = createGsonConverter();
            return (FooBar) converter.fromBody(response.getBody(), FooBar.class);
        }
    }