You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何我的自定义ClientHttpRequestInterceptor会返回空响应?

排查自定义HttpLoggingInterceptor返回空响应的问题

我帮你定位下这个问题——你的拦截器出现空响应,十有八九是因为读取响应体后没有重置输入流导致的,具体原因和解决办法如下:

核心原因

Java的InputStream(也就是响应体的输入流)是一次性读取的:当你在logResponse方法里直接读取response.getBody()的内容后,流的指针会移动到末尾,后续实际业务代码再去读取这个响应体时,就会读到空数据,最终返回空响应。而且Spring默认的ClientHttpResponse实现并不支持重置输入流,所以直接读取后就没法恢复数据了。

解决办法:包装响应体为可重复读取的缓冲流

我们可以用Spring提供的BufferedClientHttpResponseWrapper来包装原始响应,这个类会把响应体缓存到内存中,让输入流可以被多次读取。修改你的拦截器代码如下:

import org.springframework.web.client.BufferedClientHttpResponseWrapper;
import org.springframework.util.StreamUtils;
import java.nio.charset.StandardCharsets;

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 originalResponse = execution.execute(request, body);
        // 用缓冲包装器包装响应,实现可重复读取
        BufferedClientHttpResponseWrapper bufferedResponse = new BufferedClientHttpResponseWrapper(originalResponse);
        // 读取缓冲后的响应体打日志
        logResponse(bufferedResponse); 
        // 返回包装后的响应,后续业务代码可以正常读取响应体
        return bufferedResponse; 
    }

    private void logResponse(ClientHttpResponse response) throws IOException {
        // 读取响应体,因为是缓冲包装的,后续还能再读
        byte[] responseBodyBytes = StreamUtils.copyToByteArray(response.getBody());
        String responseBody = new String(responseBodyBytes, StandardCharsets.UTF_8);
        log.info("Response Status: {}, Headers: {}, Body: {}", 
                 response.getStatusCode(), response.getHeaders(), responseBody);
    }

    // 你的logRequest方法保持不变(示例实现供参考)
    private void logRequest(HttpRequest request, byte[] body) {
        String requestBody = new String(body, StandardCharsets.UTF_8);
        log.info("Request Method: {}, URI: {}, Headers: {}, Body: {}", 
                 request.getMethod(), request.getURI(), request.getHeaders(), requestBody);
    }
}

额外注意点

  • 确保你的logResponse方法使用的是包装后的BufferedClientHttpResponseWrapper实例,这样每次调用getBody()都会返回一个新的、指向流开头的输入流。
  • 如果你的响应体非常大,内存缓冲可能会有OOM风险,这种情况可以考虑只记录响应元数据(状态码、Headers),或者用临时文件来缓冲,但一般业务场景下内存缓冲足够用。

内容的提问来源于stack exchange,提问作者maya16

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:24:19