web-dev-qa-db-fra.com

Comment utiliser HttpClientBuilder avec un proxy HTTP?

J'essaie de définir le proxy pour une demande que je fais en utilisant HttpClientBuilder comme suit:

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

où constructeur est:

    HttpClientBuilder builder = HttpClientBuilder.create();

Cependant, je reçois cette exception lorsque j'exécute cette requête:

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]

(exception abrégée pour des raisons de brièveté)

Puisqu'il s'agit d'un proxy HTTP, je ne souhaite pas modifier le schéma en HTTPS, ce qui ne fonctionnera pas. Comment puis-je obtenir ce travail?

7
jobin

Java.lang.RuntimeException: org.Apache.http.conn.UnsupportedSchemeException: le protocole http n'est pas prise en charge

Pourquoi ce problème se produit?

Ans: Cela se produit réellement parce que you forget to register a connection socket factory for the 'http' scheme.

Un schéma simple 'http' doit être utilisé pour établir une connexion intermédiaireau proxy même, avant que 'https' ne puisse utiliser le tunneling.


Pour des raisons opérationnelles, vous pouvez essayer ce code:

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

Je suggérerais également un code simple pour vos recherches. J'espère que cela peut vous sauver.

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

}

Utilisez-vous l'API Java CloudantClient pour Cloudant DB?

Ans: 

Si OUI, alors le problème avec HTTP lorsque le paramétrage d’un proxy était un bogue de notre côté s’est avéré (désolé pour cela). Nous released 1.2.1 avec le correctif pour ce problème. Vous pouvez télécharger le fichier jar de ici . (Recueilli à partir de réponse de mike-rhodes )


METTRE À JOUR

Comment spécifier les informations d'identification pour le proxy ici?

De authentification HTTP ,

Par défaut, httpclient ne fournira pas d'informations d'identification à titre préventif, it will first create a HTTP request without authentication parameters. Ceci est voulu, par mesure de sécurité et dans le cadre des spécifications. Cependant, cela pose des problèmes si vous ne renouvelez pas la connexion ou si vous vous connectez à, vous vous attendez à ce que vous envoyiez des informations d'authentification lors de la première connexion. Cela entraîne également une latence supplémentaire pour une demande, car vous devez effectuer plusieurs appels et entraîne l'apparition de 401 dans les journaux.

La solution de contournement consiste à utiliser un cache d'authentification pour prétendre que vous vous êtes déjà connecté au serveur une fois. Cela signifie que vous ne ferez qu'un seul appel HTTP.

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: Vous devez faire confiance à l'hôte auquel vous vous connectez, et si vous êtes En utilisant HTTP, votre nom d'utilisateur et votre mot de passe seront envoyés en texte clair (bon, base64, mais ça ne compte pas).

Vous devriez également utiliser un Authscope beaucoup plus spécifique plutôt que en s'appuyant sur AuthScope.ANY_Host et AuthScope.ANY_PORT comme dans votre Exemple.

Le crédit va à Cetra

Liens connexes:

  1. Authentification de base HttpClientBuilder
  2. Apache HttpClient 4.1 - Authentification du proxy
16
SkyWalker

Ce que vous avez devrait être très proche du travail. Je voudrais apporter les modifications simples suivantes:

builder.useSystemProperties();

Supprimez l'appel à useSystemProperties. Cela n’est pas bien documenté, mais lorsque vous définissez le proxy (comme vous le ferez dans la ligne suivante), cela annule cette modification. Il suffit donc de supprimer cette ligne.

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

Appelez le constructeur HttpHost avec le paramètre explicite 'scheme'. C'est là que vous obtenez l'erreur, alors expliquez-le:

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

Remarque: vous ne l'avez pas dit, mais en fonction de l'utilisation de "BasicCredentialsProvider", cela ne vous donne qu'une authentification "de base". Basic est uniquement codé et n'est pas vraiment sécurisé. Pour Digest ou NTLM ou Kerberos, vous aurez besoin d'un code différent.

3
JoeG

Je pense que le problème est avec votre HttpClient, pas le proxy. Avez-vous essayé de créer votre HttpClient en utilisant HttpClientBuilder.build ()

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