Geavanceerde HttpClient-configuratie

1. Overzicht

In dit artikel zullen we kijken naar het geavanceerde gebruik van de Apache HttpClient bibliotheek.

We zullen de voorbeelden bekijken van het toevoegen van aangepaste headers aan HTTP-verzoeken, en we zullen zien hoe we de client kunnen configureren om verzoeken te autoriseren en te verzenden via een proxyserver.

We zullen Wiremock gebruiken om de HTTP-server te stoppen. Lees dit artikel als je meer wilt lezen over Wiremock.

2. HTTP-verzoek met een aangepast User-Agent Header

Laten we zeggen dat we een aangepaste User-Agent header naar een HTTP GET-verzoek. De User-Agent header bevat een karakteristieke tekenreeks waarmee de netwerkprotocol-peers het applicatietype, het besturingssysteem en de softwareleverancier of softwareversie van de aanvragende softwaregebruikersagent kunnen identificeren.

Voordat we beginnen met het schrijven van onze HTTP-client, moeten we onze embedded mock-server starten:

@Rule openbare WireMockRule serviceMock = nieuwe WireMockRule (8089);

Wanneer we een HttpGet we kunnen bijvoorbeeld gewoon een setHeader () methode om een ​​naam van onze header samen met de waarde door te geven. Die header wordt toegevoegd aan een HTTP-verzoek:

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

We voegen een User-Agent header en het verzenden van dat verzoek via een uitvoeren () methode.

Wanneer GET-verzoek wordt verzonden voor een URL /detail met koptekst User-Agent die een waarde heeft die gelijk is aan "BaeldungAgent / 1.0" dan serviceMock retourneert 200 HTTP-antwoordcode:

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

3. Verzenden van gegevens in de POST-aanvraagtekst

Wanneer we de HTTP POST-methode uitvoeren, willen we meestal een entiteit doorgeven als een verzoektekst. Bij het maken van een instantie van een HttpPost object, kunnen we de body aan dat verzoek toevoegen met een setEntity () methode:

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

We creëren een StringEntity instantie met een lichaam dat in de XML formaat. Het is belangrijk om de Inhoudstype koptekst naar "application / xml”Om informatie door te geven aan de server over het type inhoud dat we verzenden. Wanneer de serviceMock ontvangt het POST-verzoek met XML-body, het antwoordt met statuscode 200 OK:

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

4. Verzoeken verzenden via een proxyserver

Vaak kan onze webservice dat zijn achter een proxyserver die wat extra logica uitvoert, statische bronnen in de cache opslaat, enz. Wanneer we de HTTP-client maken en een verzoek naar een daadwerkelijke service sturen, willen we dat niet bij elk HTTP-verzoek behandelen.

Om dit scenario te testen, moeten we een andere embedded webserver opstarten:

@Rule openbare WireMockRule proxyMock = nieuwe WireMockRule (8090);

Met twee embedded servers is de eerste daadwerkelijke service op poort 8089 en luistert een proxyserver op poort 8090.

We zijn onze HttpClient om alle verzoeken via proxy te verzenden door een DefaultProxyRoutePlanner dat kost de HttpHost instantie proxy als een argument:

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

Onze proxyserver stuurt alle verzoeken door naar de daadwerkelijke service die luistert op de 8090-poort. Aan het einde van de test verifiëren we dat het verzoek via een proxy naar onze daadwerkelijke service is gestuurd:

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. Configureren van de HTTP-client om te autoriseren via proxy

In aanvulling op het vorige voorbeeld, zijn er enkele gevallen waarin de proxyserver wordt gebruikt om autorisatie uit te voeren. In een dergelijke configuratie kan een proxy alle verzoeken autoriseren en deze doorgeven aan de server die verborgen is achter een proxy.

We kunnen de HttpClient configureren om elk verzoek via proxy te verzenden, samen met de Autorisatie header die zal worden gebruikt om een ​​autorisatieproces uit te voeren.

Stel dat we een proxyserver hebben die slechts één gebruiker autoriseert - "gebruikersnaam_beheerder, met een wachtwoord 'geheim_wachtwoord.

We moeten het BasicCredentialsProvider instantie met inloggegevens van de gebruiker die wordt geautoriseerd via proxy. Maken HttpClient automatisch het Autorisatie header met de juiste waarde, moeten we een HttpClientContext met verstrekte inloggegevens en een BasicAuthCache die inloggegevens opslaat:

HttpHost-proxy = nieuwe HttpHost ("localhost", 8090); DefaultProxyRoutePlanner routePlanner = nieuwe DefaultProxyRoutePlanner (proxy); // Klantreferenties CredentialsProvider credentialsProvider = nieuwe BasicCredentialsProvider (); credentialsProvider.setCredentials (nieuwe AuthScope (proxy), nieuwe UsernamePasswordCredentials ("gebruikersnaam_admin", "geheim_wachtwoord")); // Maak een AuthCache-instantie AuthCache authCache = nieuwe BasicAuthCache (); BasicScheme basicAuth = nieuwe BasicScheme (); authCache.put (proxy, basicAuth); HttpClientContext context = HttpClientContext.create (); context.setCredentialsProvider (credentialsProvider); context.setAuthCache (authCache); HttpClient httpclient = HttpClients.custom () .setRoutePlanner (routePlanner) .setDefaultCredentialsProvider (credentialsProvider) .build ();

Toen we onze HttpClient, het doen van verzoeken aan onze service zal resulteren in het verzenden van een verzoek via een proxy met een Autorisatie header om het autorisatieproces uit te voeren. Het wordt automatisch in elk verzoek ingesteld.

Laten we een echt verzoek aan de service uitvoeren:

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

Verifiëren van een uitvoeren () methode op de httpClient met onze configuratie bevestigt dat een verzoek via een proxy met een Autorisatie koptekst:

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 ("Autorisatie", met ("Basic"))); serviceMock.verify (getRequestedFor (urlEqualTo ("/ private")));

6. Conclusie

Dit artikel laat zien hoe u de Apache configureert HttpClient om geavanceerde HTTP-oproepen uit te voeren. We hebben gezien hoe verzoeken via een proxyserver kunnen worden verzonden en hoe u via proxy kunt autoriseren.

De implementatie van al deze voorbeelden en codefragmenten is te vinden in het GitHub-project - dit is een Maven-project, dus het moet gemakkelijk te importeren en uit te voeren zijn zoals het is.