Configuration avancée de HttpClient

1. Vue d'ensemble

Dans cet article, nous examinerons l'utilisation avancée de la bibliothèque Apache HttpClient .

Nous examinerons les exemples d'ajout d'en-têtes personnalisés aux requêtes HTTP, et nous verrons comment configurer le client pour autoriser et envoyer des requêtes via un serveur proxy.

Nous utiliserons Wiremock pour remplacer le serveur HTTP. Si vous souhaitez en savoir plus sur Wiremock, consultez cet article.

2. Requête HTTP avec un en - tête User-Agent personnalisé

Disons que nous voulons ajouter un en - tête User-Agent personnalisé à une requête HTTP GET. L'en - tête User-Agent contient une chaîne caractéristique qui permet aux homologues de protocole réseau d'identifier le type d'application, le système d'exploitation et le fournisseur ou la version logicielle de l'agent utilisateur logiciel demandeur.

Avant de commencer à écrire notre client HTTP, nous devons démarrer notre serveur fictif intégré:

@Rule public WireMockRule serviceMock = new WireMockRule(8089);

Lorsque nous créons une instance HttpGet , nous pouvons simplement utiliser une méthode setHeader () pour passer un nom de notre en-tête avec la valeur. Cet en-tête sera ajouté à une requête HTTP:

String userAgent = "BaeldungAgent/1.0"; HttpClient httpClient = HttpClients.createDefault(); HttpGet httpGet = new HttpGet("//localhost:8089/detail"); httpGet.setHeader(HttpHeaders.USER_AGENT, userAgent); HttpResponse response = httpClient.execute(httpGet); assertEquals(response.getStatusLine().getStatusCode(), 200);

Nous ajoutons un en - tête User-Agent et envoyons cette requête via une méthode execute () .

Lorsque la demande GET est envoyée pour une URL / détail avec en- tête User-Agent qui a une valeur égale à « BaeldungAgent / 1.0 » , puis serviceMock retournera 200 code de réponse HTTP:

serviceMock.stubFor(get(urlEqualTo("/detail")) .withHeader("User-Agent", equalTo(userAgent)) .willReturn(aResponse().withStatus(200)));

3. Envoi de données dans le corps de la requête POST

Habituellement, lorsque nous exécutons la méthode HTTP POST, nous voulons passer une entité en tant que corps de requête. Lors de la création d'une instance d'un objet HttpPost , nous pouvons ajouter le corps à cette requête en utilisant une méthode setEntity () :

String xmlBody = "1"; HttpClient httpClient = HttpClients.createDefault(); HttpPost httpPost = new HttpPost("//localhost:8089/person"); httpPost.setHeader("Content-Type", "application/xml"); StringEntity xmlEntity = new StringEntity(xmlBody); httpPost.setEntity(xmlEntity); HttpResponse response = httpClient.execute(httpPost); assertEquals(response.getStatusLine().getStatusCode(), 200);

Nous créons une instance StringEntity avec un corps au format XML . Il est important de définir l'en - tête Content-Type sur « application / xml » pour transmettre des informations au serveur sur le type de contenu que nous envoyons. Lorsque le serviceMock reçoit la demande POST avec le corps XML, il répond avec le code d'état 200 OK:

serviceMock.stubFor(post(urlEqualTo("/person")) .withHeader("Content-Type", equalTo("application/xml")) .withRequestBody(equalTo(xmlBody)) .willReturn(aResponse().withStatus(200)));

4. Envoi de demandes via un serveur proxy

Souvent, notre service Web peut être derrière un serveur proxy qui exécute une logique supplémentaire, met en cache des ressources statiques, etc. Lorsque nous créons le client HTTP et envoyons une requête à un service réel, nous ne voulons pas traiter cela sur chaque requête HTTP.

Pour tester ce scénario, nous devrons démarrer un autre serveur Web intégré:

@Rule public WireMockRule proxyMock = new WireMockRule(8090);

Avec deux serveurs intégrés, le premier service réel est sur le port 8089 et un serveur proxy écoute sur le port 8090.

Nous configurons notre HttpClient pour envoyer toutes les demandes via un proxy en créant un DefaultProxyRoutePlanner qui prend le proxy d' instance HttpHost comme argument:

HttpHost proxy = new HttpHost("localhost", 8090); DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy); HttpClient httpclient = HttpClients.custom() .setRoutePlanner(routePlanner) .build(); 

Notre serveur proxy redirige toutes les demandes vers le service réel qui écoute sur le port 8090. À la fin du test, nous vérifions que la requête a bien été envoyée à notre service réel via un proxy:

proxyMock.stubFor(get(urlMatching(".*")) .willReturn(aResponse().proxiedFrom("//localhost:8089/"))); serviceMock.stubFor(get(urlEqualTo("/private")) .willReturn(aResponse().withStatus(200))); assertEquals(response.getStatusLine().getStatusCode(), 200); proxyMock.verify(getRequestedFor(urlEqualTo("/private"))); serviceMock.verify(getRequestedFor(urlEqualTo("/private")));

5. Configuration du client HTTP pour autoriser via un proxy

En prolongeant l'exemple précédent, il existe certains cas où le serveur proxy est utilisé pour effectuer une autorisation. Dans une telle configuration, un proxy peut autoriser toutes les demandes et les transmettre au serveur qui est caché derrière un proxy.

Nous pouvons configurer le HttpClient pour envoyer chaque demande via un proxy, ainsi que l'en- tête Authorization qui sera utilisé pour effectuer un processus d'autorisation.

Supposons que nous ayons un serveur proxy qui n'autorise qu'un seul utilisateur - " username_admin " , avec un mot de passe " secret_password " .

Nous devons créer l' instance BasicCredentialsProvider avec les informations d'identification de l'utilisateur qui sera autorisé via le proxy. Pour que HttpClient ajoute automatiquement l'en- tête Authorization avec la valeur appropriée, nous devons créer un HttpClientContext avec les informations d'identification fournies et un BasicAuthCache qui stocke les informations d'identification:

HttpHost proxy = new HttpHost("localhost", 8090); DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy); //Client credentials CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); credentialsProvider.setCredentials(new AuthScope(proxy), new UsernamePasswordCredentials("username_admin", "secret_password")); // Create AuthCache instance AuthCache authCache = new BasicAuthCache(); BasicScheme basicAuth = new BasicScheme(); authCache.put(proxy, basicAuth); HttpClientContext context = HttpClientContext.create(); context.setCredentialsProvider(credentialsProvider); context.setAuthCache(authCache); HttpClient httpclient = HttpClients.custom() .setRoutePlanner(routePlanner) .setDefaultCredentialsProvider(credentialsProvider) .build();

Lorsque nous configurons notre HttpClient, faire des demandes à notre service entraînera l'envoi d'une demande via un proxy avec un en- tête d' autorisation pour effectuer le processus d'autorisation. Il sera défini automatiquement dans chaque demande.

Exécutons une requête réelle au service:

HttpGet httpGet = new HttpGet("//localhost:8089/private"); HttpResponse response = httpclient.execute(httpGet, context);

La vérification d'une méthode execute () sur le httpClient avec notre configuration confirme qu'une requête est passée par un proxy avec un en- tête Authorization :

proxyMock.stubFor(get(urlMatching("/private")) .willReturn(aResponse().proxiedFrom("//localhost:8089/"))); serviceMock.stubFor(get(urlEqualTo("/private")) .willReturn(aResponse().withStatus(200))); assertEquals(response.getStatusLine().getStatusCode(), 200); proxyMock.verify(getRequestedFor(urlEqualTo("/private")) .withHeader("Authorization", containing("Basic"))); serviceMock.verify(getRequestedFor(urlEqualTo("/private")));

6. Conclusion

Cet article montre comment configurer Apache HttpClient pour effectuer des appels HTTP avancés. Nous avons vu comment envoyer des requêtes via un serveur proxy et comment autoriser via un proxy.

L'implémentation de tous ces exemples et extraits de code se trouve dans le projet GitHub - il s'agit d'un projet Maven, il devrait donc être facile à importer et à exécuter tel quel.