Erweiterte HttpClient-Konfiguration

1. Übersicht

In diesem Artikel werden wir uns mit der erweiterten Verwendung der Apache HttpClient- Bibliothek befassen .

Wir werden uns die Beispiele für das Hinzufügen von benutzerdefinierten Headern zu HTTP-Anforderungen ansehen und sehen, wie der Client so konfiguriert wird, dass Anforderungen über einen Proxyserver autorisiert und gesendet werden.

Wir werden Wiremock zum Stubben des HTTP-Servers verwenden. Wenn Sie mehr über Wiremock erfahren möchten, lesen Sie diesen Artikel.

2. HTTP-Anforderung mit einem benutzerdefinierten User-Agent- Header

Angenommen, wir möchten einer HTTP-GET-Anforderung einen benutzerdefinierten User-Agent- Header hinzufügen . Der User-Agent- Header enthält eine charakteristische Zeichenfolge, mit der die Netzwerkprotokoll-Peers den Anwendungstyp, das Betriebssystem und den Softwareanbieter oder die Softwareversion des anfordernden Software-User-Agenten identifizieren können.

Bevor wir mit dem Schreiben unseres HTTP-Clients beginnen, müssen wir unseren eingebetteten Mock-Server starten:

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

Wenn wir eine HttpGet- Instanz erstellen , können wir einfach eine setHeader () -Methode verwenden, um einen Namen unseres Headers zusammen mit dem Wert zu übergeben. Dieser Header wird einer HTTP-Anforderung hinzugefügt:

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

Wir fügen einen User-Agent- Header hinzu und senden diese Anforderung über eine execute () -Methode.

Wenn GET - Anforderung für eine URL gesendet / Detail mit Kopf User-Agent , der einen Wert hat gleich „BaeldungAgent / 1.0“ dann serviceMock werden 200 HTTP - Antwortcode zurück:

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

3. Senden von Daten im POST-Anforderungshauptteil

Wenn wir die HTTP-POST-Methode ausführen, möchten wir normalerweise eine Entität als Anforderungshauptteil übergeben. Wenn Sie eine Instanz eines HttpPost- Objekts erstellen , können Sie den Text mit einer setEntity () -Methode zu dieser Anforderung hinzufügen :

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

Wir erstellen eine StringEntity- Instanz mit einem Body im XML- Format. Es ist wichtig, den Content-Type- Header auf " application / xml " zu setzen, um Informationen über den von uns gesendeten Inhaltstyp an den Server zu übergeben. Wenn der serviceMock die POST-Anforderung mit XML-Body empfängt, antwortet er mit dem Statuscode 200 OK:

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

4. Senden von Anfragen über einen Proxyserver

Häufig befindet sich unser Webdienst hinter einem Proxyserver , der zusätzliche Logik ausführt, statische Ressourcen zwischenspeichert usw. Wenn wir den HTTP-Client erstellen und eine Anforderung an einen tatsächlichen Dienst senden, möchten wir uns damit nicht befassen jede einzelne HTTP-Anfrage.

Um dieses Szenario zu testen, müssen wir einen anderen eingebetteten Webserver starten:

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

Bei zwei eingebetteten Servern befindet sich der erste tatsächliche Dienst am 8089-Port und ein Proxyserver überwacht den 8090-Port.

Wir konfigurieren unseren HttpClient so, dass alle Anforderungen über einen Proxy gesendet werden , indem wir einen DefaultProxyRoutePlanner erstellen , der den Proxy der HttpHost- Instanz als Argument verwendet:

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

Unser Proxyserver leitet alle Anforderungen an den tatsächlichen Dienst um, der den 8090-Port überwacht. Am Ende des Tests überprüfen wir, ob die Anfrage über einen Proxy an unseren tatsächlichen Service gesendet wurde:

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. Konfigurieren des HTTP-Clients für die Autorisierung über Proxy

Wenn Sie das vorherige Beispiel erweitern, gibt es einige Fälle, in denen der Proxyserver zum Ausführen der Autorisierung verwendet wird. In einer solchen Konfiguration kann ein Proxy alle Anforderungen autorisieren und an den Server weiterleiten, der hinter einem Proxy versteckt ist.

Wir können den HttpClient so konfigurieren, dass jede Anforderung über einen Proxy zusammen mit dem Autorisierungsheader gesendet wird, der zum Ausführen eines Autorisierungsprozesses verwendet wird.

Nehmen wir an, dass wir einen Proxy - Server, die nur ein Benutzer autorisiert - „ username_admin, mit einem Kennwort „ secret_password.

Wir müssen die BasicCredentialsProvider- Instanz mit den Anmeldeinformationen des Benutzers erstellen, der über den Proxy autorisiert wird. Damit HttpClient den Authorization- Header automatisch mit dem richtigen Wert hinzufügt , müssen Sie einen HttpClientContext mit den angegebenen Anmeldeinformationen und einen BasicAuthCache erstellen , in dem die Anmeldeinformationen gespeichert werden:

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

Wenn wir unseren HttpClient einrichten und Anfragen an unseren Service stellen, wird eine Anfrage über einen Proxy mit einem Autorisierungsheader gesendet, um den Autorisierungsprozess durchzuführen. Es wird in jeder Anfrage automatisch eingestellt.

Lassen Sie uns eine tatsächliche Anforderung an den Dienst ausführen:

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

Durch Überprüfen einer execute () -Methode auf dem httpClient mit unserer Konfiguration wird bestätigt, dass eine Anforderung einen Proxy mit einem Autorisierungsheader durchlaufen hat :

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. Fazit

Dieser Artikel zeigt, wie Sie den Apache HttpClient für erweiterte HTTP-Aufrufe konfigurieren . Wir haben gesehen, wie man Anfragen über einen Proxyserver sendet und wie man über einen Proxy autorisiert.

Die Implementierung all dieser Beispiele und Codefragmente finden Sie im GitHub-Projekt - dies ist ein Maven-Projekt, daher sollte es einfach zu importieren und auszuführen sein, wie es ist.