Konfigurasi HttpClient Lanjutan

1. Ikhtisar

Pada artikel ini, kita akan melihat penggunaan lanjutan dari pustaka Apache HttpClient .

Kita akan melihat contoh menambahkan tajuk khusus ke permintaan HTTP, dan kita akan melihat cara mengkonfigurasi klien untuk mengotorisasi dan mengirim permintaan melalui server proxy.

Kami akan menggunakan Wiremock untuk mematikan server HTTP. Jika Anda ingin membaca lebih lanjut tentang Wiremock, lihat artikel ini.

2. Permintaan HTTP Dengan Header Agen-Pengguna Kustom

Misalkan kita ingin menambahkan header User-Agent kustom ke permintaan HTTP GET. The User-Agent header berisi string karakteristik yang memungkinkan rekan-rekan protokol jaringan untuk mengidentifikasi jenis aplikasi, sistem operasi, dan vendor perangkat lunak atau perangkat lunak versi dari perangkat lunak agen pengguna yang meminta.

Sebelum kita mulai menulis klien HTTP kita, kita perlu memulai server tiruan tertanam kita:

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

Saat kita membuat instance HttpGet, kita cukup menggunakan metode setHeader () untuk meneruskan nama header kita bersama dengan nilainya. Header itu akan ditambahkan ke permintaan 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);

Kami menambahkan header User-Agent dan mengirimkan permintaan itu melalui metode execute () .

Ketika permintaan GET dikirim untuk URL / detail dengan header User-Agent yang memiliki nilai sama dengan "BaeldungAgent / 1.0" maka serviceMock akan mengembalikan 200 kode respon HTTP:

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

3. Mengirim Data di Badan Permintaan POST

Biasanya, saat kami menjalankan metode HTTP POST, kami ingin meneruskan entitas sebagai badan permintaan. Saat membuat instance dari objek HttpPost , kita bisa menambahkan isi ke permintaan itu menggunakan metode 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);

Kami membuat instance StringEntity dengan badan yang berformat XML . Penting untuk menyetel header Content-Type ke " application / xml " untuk meneruskan informasi ke server tentang jenis konten yang kami kirim. Saat serviceMock menerima permintaan POST dengan badan XML, ia merespons dengan kode status 200 OK:

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

4. Mengirim Permintaan melalui Proxy Server

Seringkali, layanan web kami berada di belakang server proxy yang melakukan beberapa logika tambahan, menyimpan sumber daya statis, dll. Saat kami membuat Klien HTTP dan mengirim permintaan ke layanan yang sebenarnya, kami tidak ingin berurusan dengan itu di setiap permintaan HTTP.

Untuk menguji skenario ini, kita perlu memulai server web tertanam lain:

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

Dengan dua server tertanam, layanan aktual pertama ada di port 8089 dan server proxy mendengarkan di port 8090.

Kami mengonfigurasi HttpClient kami untuk mengirim semua permintaan melalui proxy dengan membuat DefaultProxyRoutePlanner yang menggunakan proxy instance HttpHost sebagai argumen:

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

Server proxy kami mengarahkan semua permintaan ke layanan sebenarnya yang mendengarkan di port 8090. Di akhir pengujian, kami memverifikasi bahwa permintaan telah dikirim ke layanan kami yang sebenarnya melalui 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. Mengonfigurasi Klien HTTP untuk Diotorisasi melalui Proxy

Memperluas contoh sebelumnya, ada beberapa kasus ketika server proxy digunakan untuk melakukan otorisasi. Dalam konfigurasi seperti itu, proxy dapat mengotorisasi semua permintaan dan meneruskannya ke server yang tersembunyi di balik proxy.

Kita dapat mengkonfigurasi HttpClient untuk mengirim setiap permintaan melalui proxy, bersama dengan header Otorisasi yang akan digunakan untuk melakukan proses otorisasi.

Misalkan kita memiliki server proxy yang mengotorisasi hanya satu pengguna - " username_admin " , dengan kata sandi " secret_password " .

Kita perlu membuat instance BasicCredentialsProvider dengan kredensial pengguna yang akan diotorisasi melalui proxy. Untuk membuat HttpClient secara otomatis menambahkan header Authorization dengan nilai yang tepat, kita perlu membuat HttpClientContext dengan kredensial yang disediakan dan BasicAuthCache yang menyimpan kredensial:

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

Saat kami menyiapkan HttpClient kami , membuat permintaan ke layanan kami akan mengakibatkan pengiriman permintaan melalui proxy dengan header Otorisasi untuk melakukan proses otorisasi. Ini akan diatur di setiap permintaan secara otomatis.

Mari jalankan permintaan aktual ke layanan:

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

Memverifikasi metode execute () di httpClient dengan konfigurasi kami mengonfirmasi bahwa permintaan melewati proxy dengan header Otorisasi :

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

Artikel ini menunjukkan cara mengkonfigurasi Apache HttpClient untuk melakukan panggilan HTTP lanjutan. Kami melihat cara mengirim permintaan melalui server proxy dan cara mengotorisasi melalui proxy.

Penerapan semua contoh dan cuplikan kode ini dapat ditemukan di proyek GitHub - ini adalah proyek Maven, jadi semestinya mudah untuk mengimpor dan menjalankannya apa adanya.