如何在Http代理中使用HttpClientBuilder? [英] How to use HttpClientBuilder with Http proxy?

查看:3676
本文介绍了如何在Http代理中使用HttpClientBuilder?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 HttpClientBuilder 设置代理,如下所示:

I am trying to set proxy for a request I am making using HttpClientBuilder as follows:

        CredentialsProvider credsProvider = new BasicCredentialsProvider();
        UsernamePasswordCredentials usernamePasswordCredentials = new UsernamePasswordCredentials(proxyUser, proxyPassword);
        credsProvider.setCredentials(new AuthScope(proxyHost, proxyPort), usernamePasswordCredentials);

        builder.useSystemProperties();
        builder.setProxy(new HttpHost(proxyHost, proxyPort));
        builder.setDefaultCredentialsProvider(credsProvider);
        builder.setProxyAuthenticationStrategy(new ProxyAuthenticationStrategy());

其中建造者是:

    HttpClientBuilder builder = HttpClientBuilder.create();

但是,当我执行此请求时,我收到此异常:

However, I get this exception when I execute this request:

java.lang.RuntimeException: org.apache.http.conn.UnsupportedSchemeException: http protocol is not supported
Caused by: org.apache.http.conn.UnsupportedSchemeException: http protocol is not supported
        at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:108) ~[httpclient-4.5.1.jar:4.5.1]
        at org.apache.http.impl.conn.BasicHttpClientConnectionManager.connect(BasicHttpClientConnectionManager.java:338) ~[httpclient-4.5.1.jar:4.5.1]
        at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:388) ~[httpclient-4.5.1.jar:4.5.1]
        at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236) ~[httpclient-4.5.1.jar:4.5.1]
        at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184) ~[httpclient-4.5.1.jar:4.5.1]
        at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88) ~[httpclient-4.5.1.jar:4.5.1]
        at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110) ~[httpclient-4.5.1.jar:4.5.1]
        at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184) ~[httpclient-4.5.1.jar:4.5.1]
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82) ~[httpclient-4.5.1.jar:4.5.1]
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107) ~[httpclient-4.5.1.jar:4.5.1]
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:55) ~[httpclient-4.5.1.jar:4.5.1]

(为简洁而缩短例外)

由于这是一个HTTP代理,我不想将方案更改为HTTPS,无论如何都无法工作。我如何使这个工作?

Since this is an HTTP proxy, I don't want to change the scheme to HTTPS, which anyways won't work. How do I get this working?

推荐答案


java.lang.RuntimeException:
org .apache.http.conn.UnsupportedSchemeException:http协议不支持

java.lang.RuntimeException: org.apache.http.conn.UnsupportedSchemeException: http protocol is not supported



为什么会出现此问题?



Ans:这实际上是因为您忘记为'http'方案注册连接套接字工厂

Why this problem occurs?

Ans: This actually happens because you forget to register a connection socket factory for the 'http' scheme.

普通'http'方案必须用于建立代理本身的中间连接
之前'https'可以使用隧道。

Plain 'http' scheme must be used to establish an intermediate connection to the proxy itself before 'https' tunneling could be employed.

用于操作目的,您可以尝试以下代码:

For operational purpose, you can try this code:

CloseableHttpClient client = HttpClients.custom()
           .setRoutePlanner(new
 SystemDefaultRoutePlanner(ProxySelector.getDefault()))
           .build();






我还建议您进行简单的研究代码。希望它能救你。


I would also suggest simple code for your research. Hope it can save you.

ClientExecuteProxy.java

package org.apache.http.examples.client;

import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

/**
 * How to send a request via proxy.
 *
 * @since 4.0
 */
public class ClientExecuteProxy {

    public static void main(String[] args)throws Exception {
        CloseableHttpClient httpclient = HttpClients.createDefault();
        try {
            HttpHost target = new HttpHost("httpbin.org", 443, "https");
            HttpHost proxy = new HttpHost("127.0.0.1", 8080, "http");

            RequestConfig config = RequestConfig.custom()
                    .setProxy(proxy)
                    .build();
            HttpGet request = new HttpGet("/");
            request.setConfig(config);

            System.out.println("Executing request " + request.getRequestLine() + " to " + target + " via " + proxy);

            CloseableHttpResponse response = httpclient.execute(target, request);
            try {
                System.out.println("----------------------------------------");
                System.out.println(response.getStatusLine());
                System.out.println(EntityUtils.toString(response.getEntity()));
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }
    }

}

您是否正在使用CloudantClient Java API for Cloudant DB?

答案

如果是,则说明设置时遇到HTTP问题代理是我们最后的一个错误(抱歉)。我们发布了1.2.1 并解决了这个问题。您可以从此处下载jar文件。 (收集自 mike-rhodes的回答

If YES, then It turned out the issue with HTTP when setting a proxy was a bug at our end (sorry about that). We released 1.2.1 with the fix for this problem. You can download jar file from here. (Collected from mike-rhodes's answer)


如何指定凭据?这里的代理?

来自 HTTP身份验证

默认情况下,httpclient不会抢先提供凭据,它将首先创建一个没有身份验证参数的HTTP请求。这是设计,作为安全预防措施,并作为规范的一部分。但是,如果您不重试连接,或者您要连接的任何地方都希望您在第一个连接上发送身份验证详细信息,则会导致问题。它还会导致请求的额外延迟,因为您需要进行多次调用,并导致401s出现在日志中。

By default, httpclient will not provide credentials preemptively, it will first create a HTTP request without authentication parameters. This is by design, as a security precaution, and as part of the spec. But, this causes issues if you don't retry the connection, or wherever you're connecting to expects you to send authentication details on the first connection. It also causes extra latency to a request, as you need to make multiple calls, and causes 401s to appear in the logs.

解决方法是使用身份验证缓存来假装你已经连接到服务器一次。这意味着你只能进行一次HTTP调用。

The workaround is to use an authentication cache to pretend that you've already connected to the server once. This means you'll only make one HTTP call.

CloseableHttpClient httpclient = HttpClientBuilder.create().build();

HttpHost targetHost = new HttpHost("localhost", 80, "http");
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
        new AuthScope(targetHost.getHostName(), targetHost.getPort()),
        new UsernamePasswordCredentials("username", "password"));

// Create AuthCache instance
AuthCache authCache = new BasicAuthCache();
// Generate BASIC scheme object and add it to the local auth cache
BasicScheme basicAuth = new BasicScheme();
authCache.put(targetHost, basicAuth);

// Add AuthCache to the execution context
HttpClientContext context = HttpClientContext.create();
context.setCredentialsProvider(credsProvider);
context.setAuthCache(authCache);

HttpGet httpget = new HttpGet("/");
for (int i = 0; i < 3; i++) {
    CloseableHttpResponse response = httpclient.execute(
            targetHost, httpget, context);
    try {
        HttpEntity entity = response.getEntity();

    } finally {
        response.close();
    }
}




注意:你需要信任您正在连接的主机,如果您使用HTTP
,您的用户名和密码将以明文
发送(嗯,base64,但不计算在内)。

N.B: You need to trust the host you're connecting to, and if you're using HTTP, your username and password will be sent in cleartext (well, base64, but that doesn't count).

您还应该使用更具体的Authscope而不是
,依赖于 AuthScope.ANY_HOST AuthScope.ANY_PORT 就像你的
例子一样。

You should also be using a much more specific Authscope rather than relying on AuthScope.ANY_HOST and AuthScope.ANY_PORT like in your example.

信用转到< a href =https://stackoverflow.com/users/15087/cetra> Cetra

相关链接:


  1. HttpClientBuilder基本身份验证

  2. Apache HttpClient 4.1 - 代理验证

  1. HttpClientBuilder basic auth
  2. Apache HttpClient 4.1 - Proxy Authentication

这篇关于如何在Http代理中使用HttpClientBuilder?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆