首页 > 解决方案 > 如何使用 apache java HttpClient 4.5 从 CONNECT 请求中检索响应标头?

问题描述

我使用 http 代理通过 CloseableHttpClient 连接到 https 网站。首先发送 CONNECT 请求,因为它必须进行隧道连接。将发送响应标头,我需要检索它们。结果将存储在变量中并稍后使用。

在 HttpClient 4.2 上,我可以使用 HttpResponseInterceptor 来实现它:

final DefaultHttpClient httpClient = new DefaultHttpClient();
//configure proxy


httpclient.addResponseInterceptor(new HttpResponseInterceptor() {
    public void process(HttpResponse httpResponse, HttpContext httpContext) throws HttpException, IOException {
        final Header[] headers = httpResponse.getAllHeaders();

        //store headers
    }
});

但是当我使用 HttpClient 4.5 时,我的响应拦截器永远不会在 CONNECT 请求上调用。它直接在 GET 或 POST 请求上跳转:

 final CloseableHttpClient httpClient = HttpClients.custom()
                .setProxy(new HttpHost(proxyHost, proxyPort, "http"))
                .addInterceptorFirst(new HttpResponseInterceptor() {
                    public void process(HttpResponse httpResponse, HttpContext httpContext) throws HttpException, IOException {
                        final Header[] headers = httpResponse.getAllHeaders();

                        //store headers
                    }
                }).build();

方法setInterceptorLast()和的结果相同setHttpProcessor()。提前致谢 :)

标签: javaapache-httpclient-4.x

解决方案


您将需要一个自定义HttpClientBuilder类,以便能够将自定义协议拦截器添加到用于执行CONNECT方法的 HTTP 协议处理器。

HttpClient 4.5 它并不漂亮,但它会完成工作:

HttpClientBuilder builder = new HttpClientBuilder() {

    @Override
    protected ClientExecChain createMainExec(
            HttpRequestExecutor requestExec,
            HttpClientConnectionManager connManager,
            ConnectionReuseStrategy reuseStrategy,
            ConnectionKeepAliveStrategy keepAliveStrategy,
            HttpProcessor proxyHttpProcessor,
            AuthenticationStrategy targetAuthStrategy,
            AuthenticationStrategy proxyAuthStrategy,
            UserTokenHandler userTokenHandler) {

        final ImmutableHttpProcessor myProxyHttpProcessor = new ImmutableHttpProcessor(
                Arrays.asList(new RequestTargetHost()),
                Arrays.asList(new HttpResponseInterceptor() {

                    @Override
                    public void process(
                            HttpResponse response,
                            HttpContext context) throws HttpException, IOException {

                    }
                })
        );

        return super.createMainExec(requestExec, connManager, reuseStrategy, keepAliveStrategy,
                myProxyHttpProcessor, targetAuthStrategy, proxyAuthStrategy, userTokenHandler);
    }

};

HttpClient 5.0 经典

CloseableHttpClient httpClient = HttpClientBuilder.create()
        .replaceExecInterceptor(ChainElement.CONNECT.name(),
                new ConnectExec(
                        DefaultConnectionReuseStrategy.INSTANCE,
                        new DefaultHttpProcessor(new RequestTargetHost()),
                        DefaultAuthenticationStrategy.INSTANCE))
        .build();

推荐阅读