Complete Debugging and Logging for Spring RestTemplate Requests and Responses

Nov 21, 2025 · Programming · 11 views · 7.8

Keywords: Spring RestTemplate | Debugging Logs | HTTP Client

Abstract: This article provides a comprehensive guide to enabling full debugging and logging for Spring RestTemplate, focusing on capturing detailed request and response information through log level configuration and interceptor implementation. It analyzes multiple implementation approaches, including custom ClientHttpRequestInterceptor, Apache HttpClient log configuration, and simplified setup in Spring Boot environments, with complete code examples and configuration instructions to help developers achieve verbose debugging output similar to curl -v.

Introduction

In RESTful service development based on the Spring framework, RestTemplate serves as a core HTTP client component, and its debugging and logging capabilities are crucial for problem diagnosis and system monitoring. Many developers face challenges in obtaining complete request and response information during practical use. This article systematically introduces multiple effective debugging solutions based on high-scoring Stack Overflow answers and real project experience.

Core Debugging Solutions Analysis

According to community practices and project verification, there are two main technical approaches to achieve complete RestTemplate debugging logs: configuration-based methods using logging frameworks and custom implementations using interceptors.

Logging Framework Configuration Method

In Spring Boot environments, the most concise configuration is to add the following to the application.properties file:

logging.level.org.springframework.web.client.RestTemplate=DEBUG

This configuration outputs debug information from within RestTemplate, including key stages such as request construction and response processing. It should be noted that this configuration may have compatibility differences across Spring Boot versions and is recommended for use in the latest stable releases.

For scenarios using Apache HttpClient as the underlying implementation, more granular log levels can be configured:

logging.level.org.apache.http=DEBUG

Or enable only network layer logging:

logging.level.org.apache.http.wire=DEBUG

This configuration outputs complete HTTP protocol interaction details, including request headers, response headers, entity content, etc., similar to the verbose output effect of the curl tool.

SLF4J and Log4j Integration Configuration

In traditional Spring projects using SLF4J with Log4j, add the following to the log4j.properties file:

log4j.logger.httpclient.wire=DEBUG

Additionally, ensure the following configurations are correct:

  1. Exclude commons-logging dependencies from the classpath to avoid logging framework conflicts
  2. Ensure the log4j.properties file is located in an accessible classpath location
  3. Verify SLF4J binding configuration is correct

In Maven projects, commons-logging can be excluded through the following configuration:

<exclusions>
    <exclusion>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
    </exclusion>
</exclusions>

Custom Interceptor Implementation

For scenarios requiring finer control, implement the ClientHttpRequestInterceptor interface to customize logging logic:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;

public class LoggingRequestInterceptor implements ClientHttpRequestInterceptor {
    
    private static final Logger log = LoggerFactory.getLogger(LoggingRequestInterceptor.class);
    
    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, 
                                       ClientHttpRequestExecution execution) throws IOException {
        traceRequest(request, body);
        ClientHttpResponse response = execution.execute(request, body);
        traceResponse(response);
        return response;
    }
    
    private void traceRequest(HttpRequest request, byte[] body) {
        log.info("=== 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.info("=== Request End ===");
    }
    
    private void traceResponse(ClientHttpResponse response) throws IOException {
        StringBuilder responseBody = new StringBuilder();
        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(response.getBody(), "UTF-8"))) {
            String line;
            while ((line = reader.readLine()) != null) {
                responseBody.append(line).append("\n");
            }
        }
        
        log.info("=== Response Begin ===");
        log.debug("Status Code: {}", response.getStatusCode());
        log.debug("Status Text: {}", response.getStatusText());
        log.debug("Headers: {}", response.getHeaders());
        log.debug("Response Body: {}", responseBody.toString());
        log.info("=== Response End ===");
    }
}

Configure RestTemplate to use the custom interceptor:

RestTemplate restTemplate = new RestTemplate();
restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(
    new SimpleClientHttpRequestFactory()));

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

Using BufferingClientHttpRequestFactory is crucial because the default HTTP request factory only allows reading the response body once, while both the interceptor and business code need to access the response content.

Practical Application Scenarios Analysis

Referring to error logs from actual projects, such as ResourceAccessException, complete debugging logs can help quickly locate common issues like network connection problems, request parameter errors, and response parsing exceptions.

In microservices architecture, detailed HTTP interaction logs provide significant value for inter-service call monitoring, performance analysis, and fault troubleshooting. Through appropriate log level configuration, verbose logs can be enabled during development and debugging phases, while adjusted to appropriate levels in production environments to balance performance and observability.

Best Practices Recommendations

  1. Enable DEBUG level logs in development environments and adjust according to actual conditions in production
  2. Consider data masking before log output for sensitive information
  3. Use asynchronous logging frameworks to avoid I/O blocking impacts on performance
  4. Regularly clean log files to prevent disk space exhaustion
  5. Combine with APM tools for more comprehensive system monitoring

Conclusion

Complete debugging and logging for Spring RestTemplate can be achieved through various methods, from simple configuration adjustments to complex custom interceptor development. Developers should choose the most suitable solution based on specific requirements and environments, balancing functionality, performance, and maintenance costs. Proper debugging configuration can significantly improve development efficiency and system maintainability.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.