Home » Android » java – Read the response body in an Android Spring Interceptor

java – Read the response body in an Android Spring Interceptor

Posted by: admin June 15, 2020 Leave a comment

Questions:

I’m using a simple Spring Interceptor class to log all REST requests/responses for the RestTemplate object in my Android app. So far everything works fine.

public class LoggerInterceptor implements ClientHttpRequestInterceptor {

@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body,
  ClientHttpRequestExecution execution) throws IOException {

Log.d(TAG, "Request body: " + new String(body));
// ...more log statements...

ClientHttpResponse response = execution.execute(request, body);

Log.d(TAG, "Response Headers: " + response.getHeaders());

return response;
}

At initialization I call:

List<ClientHttpRequestInterceptor> interceptors = new ArrayList<ClientHttpRequestInterceptor>();
LoggerInterceptor loggerInterceptor = new LoggerInterceptor();
interceptors.add(loggerInterceptor);
restTemplate.setInterceptors(interceptors);

However I cannot log response.getBody() in the method above because the InputStream gets consumed once and throws an IllegalStateException when it is consumed again later. Is there a way around this so that I can log the response body too?

How to&Answers:

To allow for multiple response.getBody() calls wrap your ClientHttpRequestFactory in a BufferingClientHttpRequestFactory.

ClientHttpRequestFactory requestFactory = 
    new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory());
restTemplate.setRequestFactory(requestFactory);

Answer:

Implement ClientHttpResponse yourself and add a setBody(byte[] body) method and override getBody. In your code above, you can then store the byte array in an ByteArrayInputStream, log what you want, then set the byte array back in the instance of your class that implements ClientHttpResponse, and that you can then return.