web-dev-qa-db-ja.com

HttpClientBuilderとHttpプロキシを使用するには?

次のようにHttpClientBuilderを使用して作成するリクエストにプロキシを設定しようとしています。

        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();

ただし、このリクエストを実行するとこの例外が発生します。

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に変更したくありませんが、とにかく機能しません。これをどのように機能させるのですか?

10
jobin

Java.lang.RuntimeException:org.Apache.http.conn.UnsupportedSchemeException:httpプロトコルはサポートされていません

なぜこの問題が発生するのですか?

Ans:これは、you forget to register a connection socket factory for the 'http' schemeが原因で実際​​に発生します。

'http'トンネリングを使用する前に、プレーン'https'スキームを使用してプロキシ自体への中間接続を確立する必要があります。


操作目的で、次のコードを試すことができます。

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

また、あなたの研究のための簡単なコードを提案します。それがあなたを救うことを願っています。

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 Cloudant DBのAPIを使用していますか?

Ans:

はいの場合、プロキシの設定がHTTPの問題であることが判明しました(これについてはごめんなさい)。この問題の修正をreleased 1.2.1します。 jarファイルは here からダウンロードできます。 ( マイクロードスの回答 )から収集


[〜#〜] update [〜#〜]

ここでプロキシの資格情報を指定するにはどうすればよいですか?

HTTP認証 から、

デフォルトでは、httpclientはit will first create a HTTP request without authentication parametersという資格情報をプリエンプティブに提供しません。これは、セキュリティ上の予防措置として、および仕様の一部として、設計によるものです。ただし、接続を再試行しない場合、または最初の接続で認証の詳細を送信することを期待している接続先であれば、これにより問題が発生します。また、複数の呼び出しを行う必要があるため、リクエストに余分な遅延が発生し、ログに401が表示されます。

回避策は、認証キャッシュを使用して、サーバーに既に一度接続したことを装います。これは、HTTP呼び出しを1回だけ行うことを意味します。

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();
    }
}

N.B:接続しているホストを信頼する必要があります。HTTPを使用している場合、ユーザー名とパスワードはクリアテキストで送信されます(もちろんbase64ですが、カウントされません)。

また、例のようにAuthScope.ANY_HostおよびAuthScope.ANY_PORTに依存するのではなく、より具体的なAuthscopeを使用する必要があります。

クレジットは Cet​​ra

関連リンク:

  1. HttpClientBuilder基本認証
  2. Apache HttpClient 4.1-プロキシ認証
16
SkyWalker

あなたが持っているものは仕事に非常に近いはずです。次の簡単な変更を行います。

builder.useSystemProperties();

UseSystemPropertiesへの呼び出しを削除します。よく文書化されていませんが、プロキシを設定すると(次の行で行うように)、これがオーバーライドされるため、その行を削除してください。

builder.setProxy(new HttpHost(proxyHost, proxyPort));

明示的な 'scheme'パラメーターを使用してHttpHostコンストラクターを呼び出します。これはエラーが発生する場所ですので、明確にしてください:

String proxyScheme = "http";
builder.setProxy(new HttpHost(proxyHost, proxyPort, proxyScheme));

注:言わなかったが、「BasicCredentialsProvider」の使用法に基づいて、これは「Basic」認証のみを提供しています。 Basicはエンコードされているだけで、実際には安全ではありません。ダイジェストまたはNTLMまたはKerberosの場合、異なるコードが必要になります。

4
JoeG

問題はプロキシではなく、HttpClientにあると思います。 HttpClientBuilder.build()を使用してHttpClientを作成しようとしましたか

HttpClient client = builder.build();
2
An Do