【问题标题】:apache commons httpclient 4.3.5 via http proxy通过http代理的apache commons httpclient 4.3.5
【发布时间】:2015-01-04 15:08:52
【问题描述】:

大约两天以来,我一直在努力解决一个问题,似乎没有找到解决方案。

为了在我们的产品中改进对系统代理设置的支持,我编写了一个测试应用程序,对一个小型 http 代理服务器进行一些测试,我在一个 docker 映像中运行。

一方面,我与普通的 URL.openStream() 建立了连接……效果很好。它识别我的开发者框设置,我指向 docker run squid 或 tinyproxy,它可以从网络下载文件。

我用 httpclient 3.X 和 4.X 做同样的测试。连接到两个代理时,两者都因超时错误而失败。 由于两者具有相同的行为,我只选择我的 httpclient 4.x 配置来显示:

public void testDownloadWithHTTPClient4() throws ClientProtocolException, IOException {
    System.out.println("DOWNLOADTEST httpclient 4.x");
    RequestConfig config = RequestConfig.custom().setSocketTimeout(TIMEOUT * 1000)
            .setConnectTimeout(TIMEOUT * 1000).setConnectionRequestTimeout(TIMEOUT * 1000).build();

    CloseableHttpClient httpclient = HttpClientBuilder.create()
            .setRoutePlanner(new SystemDefaultRoutePlanner(ProxySelector.getDefault()))
            .setDefaultRequestConfig(config).build();

    try {
        HttpGet httpget = new HttpGet(DOWNLOADURL);
        System.out.println("Executing request " + httpget.getRequestLine());

        ResponseHandler<Boolean> resStreamHandler = new ResponseHandler<Boolean>() {

            @Override
            public Boolean handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
                int status = response.getStatusLine().getStatusCode();
                if (status >= 200 && status < 300) {
                    HttpEntity entity = response.getEntity();
                    String currentDirectory = new java.io.File(".").getCanonicalPath();
                    File destinationFile = new File(currentDirectory, myfile.war");
                    FileUtils.copyInputStreamToFile(entity.getContent(), destinationFile);
                    return true;
                } else {
                    throw new ClientProtocolException("Unexpected response status: " + status);
                }
            }
        };

        httpclient.execute(httpget, resStreamHandler);
    } finally {
        httpclient.close();
    }
}

我之前也打过电话

public void prepareProxysettings() {
    // try to get system preferences for proxy-settings
    Properties props = System.getProperties();
    props.setProperty("java.net.useSystemProxies", "true");
}

结果是,客户端似乎认识到要使用代理,但随后失败并出现以下异常:

org.apache.http.conn.ConnectTimeoutException: Connect to 172.16.7.48:6666 [/172.16.7.48] failed: Connect timed out
at org.apache.http.impl.conn.HttpClientConnectionOperator.connect(HttpClientConnectionOperator.java:132)
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:318)
at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:371)
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:219)
[...]
Caused by: java.net.SocketTimeoutException: Connect timed out
at java.net.SocksSocketImpl.readSocksReply(SocksSocketImpl.java:125)

现在我被卡住了,不知道该怎么办。显然,代理设置并没有那么错误,因为我使用 URL 进行的普通下载是有效的。 httpclient 也认识到需要代理。但是为什么它会发送一个请求,这两个不同的 http 代理都不理解呢?

非常感谢任何帮助!

【问题讨论】:

  • 谢谢罗伯特!看着这堂课,这给我留下的印象是,我在这里遗漏了什么?我找到了示例,演示了如何设置代理连接,就像我在上面的代码中所做的那样。这有什么“错误”?为什么我必须深入到底层套接字?我用 squid 和 tinyproxy 对此进行了测试,两者的行为相同。我预计,像“通过代理请求”示例或通过路由在 http-client 级别设置代理会导致客户端通过代理发送 http-connections。
  • 如果您只是设置代理,则无需参与套接字。这只是为了给出一些 apache 类/包的实际示例。

标签: java http proxy timeout apache-httpclient-4.x


【解决方案1】:

最后我想我发现了我的设置出了什么问题。 愚蠢的我,将我的开发人员桌面(win7)配置为使用我的测试代理。但是我保留了默认行为,就像对所有可能类型的连接使用此代理一样。如果我这样做,我会通过 httpclients 获得描述的 timouets。

只要我为 http-connections 配置代理,只有所有下载方式都可以正常工作,并且 tinyproxy 的日志证明,我的连接是通过代理路由的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-30
    • 1970-01-01
    • 1970-01-01
    • 2011-02-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多