It’s sometimes useful to log HTTP requests and responses when working with a Spring RestTemplate. If you need fine-grained control over exactly what’s logged you can use a custom interceptor to add logging before and after the remote call.

Creating an Interceptor

You’ll need to create a class that extends ClientHttpRequestInterceptor and implement the intercept method as shown below.

@Slf4j
@Component
public class LoggingInterceptor implements ClientHttpRequestInterceptor {
 
    @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 {
        
    	if (log.isDebugEnabled()) {
            log.debug("===========================request begin================================================");
            log.debug("URI         : {}", request.getURI());
            log.debug("Method      : {}", request.getMethod());
            log.debug("Headers     : {}", request.getHeaders());
            log.debug("Request body: {}", new String(body, "UTF-8"));
            log.debug("==========================request end================================================");
        }
    }
 
    private void logResponse(ClientHttpResponse response) throws IOException {
        
    	if (log.isDebugEnabled()) {
            log.debug("============================response begin==========================================");
            log.debug("Status code  : {}", response.getStatusCode());
            log.debug("Status text  : {}", response.getStatusText());
            log.debug("Headers      : {}", response.getHeaders());
            log.debug("Response body: {}", StreamUtils.copyToString(response.getBody(), Charset.defaultCharset()));
            log.debug("=======================response end=================================================");
        }
    }
}

When this class is registered with a RestTemplate Spring will call the intercept method before the request is dispatched, which allows you to log the request. In the logRequest method, I’ve grabbed information from the request that I want to log. Obviously, you can log as much or as little as you like here.

After logging the request I call the execute method on the ClientHttpRequestExecution object to dispatch the request. When the response is received I log the status, headers and body.

Configuring the RestTemplate

To make sure the interceptor is called you’ll need to register it with the RestTemplate .  In the example below I’ve added just the LoggingInterceptor, but you’re free to add multiple interceptors and Spring will chain them together for you at runtime.

@Bean
public RestTemplate createRestTemplate(LoggingInterceptor loggingInterceptor, RestErrorHandler restErrorHandler) {
    
  RestTemplate restTemplate = new RestTemplate();
  restTemplate.setInterceptors(Collections.singletonList(loggingInterceptor));
    
  return restTemplate;
}

You can of course just enable debug logging on the RestTemplate package but I like using an interceptor as if gives you fine-grained control to log exactly what you want.