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

如何同时记录HttpRequest与HttpResponse并获取拦截器添加的请求信息?

Apache HttpClient 同时记录处理后的请求与响应日志方案

要解决拦截器修改请求后无法获取最终请求对象的问题,核心思路是利用HttpClient的**请求上下文(HttpContext)**存储经过所有拦截器处理后的请求,再在响应拦截器中取出该请求与响应一起完成日志记录。具体实现步骤如下:

1. 定义请求拦截器,存储处理后的请求

创建一个请求拦截器,在所有内置拦截器处理完请求后,将最终的请求对象存入上下文:

public class RequestStorageInterceptor implements HttpRequestInterceptor {
    // 上下文存储键,自定义即可
    public static final String PROCESSED_REQUEST_KEY = "final_http_request";

    @Override
    public void process(HttpRequest request, HttpContext context) throws HttpException, IOException {
        // 将处理完毕的请求存入上下文
        context.setAttribute(PROCESSED_REQUEST_KEY, request);
    }
}

2. 定义响应拦截器,结合请求与响应日志

创建响应拦截器,从上下文中取出之前存储的最终请求,调用你的日志方法完成联合记录:

public class RequestResponseLoggingInterceptor implements HttpResponseInterceptor {
    private final HttpClientLogger httpClientLogger;

    public RequestResponseLoggingInterceptor(HttpClientLogger logger) {
        this.httpClientLogger = logger;
    }

    @Override
    public void process(HttpResponse response, HttpContext context) throws HttpException, IOException {
        // 从上下文获取处理后的请求
        HttpRequest processedRequest = (HttpRequest) context.getAttribute(RequestStorageInterceptor.PROCESSED_REQUEST_KEY);
        if (processedRequest != null) {
            // 同时传入请求和响应记录日志
            httpClientLogger.logRequestResponse(processedRequest, response);
        }
    }
}

3. 修改HttpClient构建逻辑,添加拦截器

在构建HttpClient时,将上述两个拦截器加入构建器:

@Override
public HttpResponse send(String method, String path, Map<String, String> headers, HttpEntity httpEntity) throws IOException {
    HttpUriRequest request = getHttpUriRequest(method, path, headers, httpEntity);

    // 构建HttpClient时添加拦截器
    try (CloseableHttpClient httpClient = httpClientBuilder
            .addInterceptorLast(new RequestStorageInterceptor()) // 最后执行请求拦截器,确保存入最终请求
            .addInterceptorFirst(new RequestResponseLoggingInterceptor(httpClientLogger)) // 优先执行响应拦截器
            .build()) {
        return httpClient.execute(request);
    }
}

方案说明

  • 请求拦截器使用addInterceptorLast:保证它在所有内置拦截器(比如添加默认头、处理编码的拦截器)之后执行,存入的是实际发送给服务器的最终请求对象。
  • 响应拦截器使用addInterceptorFirst:确保在其他响应拦截器处理之前完成日志记录,避免响应被修改后日志失真。
  • 通过HttpContext传递请求对象:完全规避了HttpClient内部复制请求导致的原始对象与实际请求不一致的问题,拿到的请求是经过所有拦截器处理后的完整版本。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 19:50:12