Why my custom ClientHttpRequestInterceptor with empty response
interceptor, resttemplate, spring
Solution
Since the input stream can be consumed only once and there is no `reset()` or `mark(***)` function available for `sun.net.www.protocol.http.HttpURLConnection$HttpInputStream`.
There is only one way to read the response multiple time by creating the restTemplate in the following way.
@Bean
public RestTemplate getfxoWsClientRestTemplate(){
RestTemplate restTemplate = new RestTemplate(new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory()));
restTemplate.setInterceptors(Collections.singletonList(new HttpLoggingInterceptor()));
return restTemplate;
}
And the `LoggingIntercepter` can be written like this
public class HttpLoggingInterceptor implements ClientHttpRequestInterceptor {
private final static Logger logger = LoggerFactory.getLogger(HttpLoggingInterceptor.class);
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
logger.info("request method: {}, request URI: {}, request headers: {}, request body: {}",
request.getMethod(), request.getURI(), request.getHeaders(), new String(body, Charset.forName("UTF-8")));
ClientHttpResponse response = execution.execute(request, body);
logger.info("response status code: {}, response headers: {}, response body: {}",
response.getStatusCode(), response.getHeaders(), new String(ByteStreams.toByteArray(response.getBody()), Charset.forName("UTF-8")));
return response;
}
}
Problem
I have done the following for my custom logging interceptor ``` public class HttpLoggingInterceptor implements ClientHttpRequestInterceptor { private final static Logger log = LoggerFactory.getLogger(HttpLoggingInterceptor.class); @Override public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { logRequest(request, body); ClientHttpResponse response = execution.execute(request, body); logResponse(response); return response; } private void logRequest(HttpRequest request, byte[] body) throws IOException { log.info("Request URI : {}, Method : {}, Headers : {}, Request body : {}", request.getURI(), request.getMethod(), request.getHeaders(), new String(body, "UTF-8")); } private void logResponse(ClientHttpResponse response) throws IOException { log.info("Response Status code : {}, Status text : {}, Headers : {}, Response body: {}", response.getStatusCode(), response.getStatusText(), response.getHeaders(), StreamUtils.copyToString(response.getBody(), Charset.defaultCharset())); } } ``` And I am setting the intercepter to the restTemplate ``` @Autowired public RestTemplate restTemplate; @Override public void onApplicationEvent(ApplicationReadyEvent event) { List<ClientHttpRequestInterceptor> clientHttpRequestInterceptors = new ArrayList<>(); clientHttpRequestInterceptors.add(new HttpLoggingInterceptor()); // clientHttpRequestInterceptors.addAll(restTemplate.getInterceptors()); restTemplate.setInterceptors(clientHttpRequestInterceptors); // restTemplate.setInterceptors(Collections.singletonList(new HttpLoggingInterceptor())); } ``` The logger is printing the response properly to the console, But at the end the response is returned as empty to the caller. I am not able to debug and figure it out. I have figured it out that the `StreamUtils.copyToString(response.getBody(), Charset.defaultCharset())` is reading the input stream once and it is no more holding the response body in it (which is empty now) Anyone else also facing the same issue and has any idea of duplicating the InputStream without reading it from the original InputStream?