URL yang tidak dipendekkan dengan HttpClient

1. Gambaran keseluruhan

Dalam artikel ini kita akan menunjukkan bagaimana cara mengecilkan URL menggunakan HttpClient .

Satu contoh mudah adalah apabila URL asal telah dipendekkan sekali - dengan perkhidmatan seperti bit.ly .

Contoh yang lebih rumit adalah apabila URL telah dipendekkan berkali-kali , oleh perkhidmatan yang berbeza, dan memerlukan beberapa hantaran untuk sampai ke URL penuh yang asal.

Sekiranya anda ingin menggali lebih mendalam dan mengetahui perkara menarik lain yang boleh anda lakukan dengan HttpClient - teruskan ke tutorial HttpClient utama .

2. Unshorten URL Sekali

Mari kita mulakan - pendekkan URL yang hanya melalui perkhidmatan URL pendekkan sekali.

Perkara pertama yang kami perlukan adalah klien http yang tidak mengikuti pengalihan secara automatik :

CloseableHttpClient client = HttpClientBuilder.create().disableRedirectHandling().build();

Ini perlu kerana kita perlu memintas tindak balas pengalihan secara manual dan mengeluarkan maklumat daripadanya.

Kami mulakan dengan mengirimkan permintaan ke URL yang dipendekkan - respons yang kami terima adalah 301 yang Dipindahkan secara Tetap .

Kemudian, kita perlu mengekstrak tajuk Lokasi yang menunjukkan yang berikutnya, dan dalam kes ini - URL akhir:

public String expandSingleLevel(String url) throws IOException { HttpHead request = null; try { request = new HttpHead(url); HttpResponse httpResponse = client.execute(request); int statusCode = httpResponse.getStatusLine().getStatusCode(); if (statusCode != 301 && statusCode != 302) { return url; } Header[] headers = httpResponse.getHeaders(HttpHeaders.LOCATION); Preconditions.checkState(headers.length == 1); String newUrl = headers[0].getValue(); return newUrl; } catch (IllegalArgumentException uriEx) { return url; } finally { if (request != null) { request.releaseConnection(); } } }

Akhirnya, ujian langsung mudah untuk memperluaskan URL:

@Test public void givenShortenedOnce_whenUrlIsUnshortened_thenCorrectResult() throws IOException { String expectedResult = "/rest-versioning"; String actualResult = expandSingleLevel("//bit.ly/13jEoS1"); assertThat(actualResult, equalTo(expectedResult)); }

3. Memproses Beberapa Tahap URL

Masalah dengan URL pendek ialah URL tersebut dapat dipendekkan berkali-kali , dengan perkhidmatan yang sama sekali berbeza. Memperluas URL seperti itu akan memerlukan banyak pas untuk sampai ke URL asal.

Kami akan menerapkan operasi primitif expandSingleLevel yang ditentukan sebelumnya untuk hanya melakukan lelaran melalui semua URL perantara dan sampai ke sasaran akhir :

public String expand(String urlArg) throws IOException { String originalUrl = urlArg; String newUrl = expandSingleLevel(originalUrl); while (!originalUrl.equals(newUrl)) { originalUrl = newUrl; newUrl = expandSingleLevel(originalUrl); } return newUrl; }

Sekarang, dengan mekanisme baru memperluas pelbagai peringkat URL, mari kita tentukan ujian dan buat ini:

@Test public void givenShortenedMultiple_whenUrlIsUnshortened_thenCorrectResult() throws IOException { String expectedResult = "/rest-versioning"; String actualResult = expand("//t.co/e4rDDbnzmk"); assertThat(actualResult, equalTo(expectedResult)); }

Kali ini, URL pendek - //t.co/e4rDDbnzmk - yang sebenarnya dipendekkan dua kali - sekali melalui bit.ly dan kali kedua melalui perkhidmatan t.co - diperluaskan dengan betul ke URL asal.

4. Kesan pada Redirect Loops

Akhirnya, beberapa URL tidak dapat dikembangkan kerana membentuk gelung pengalihan. Masalah seperti ini akan dapat dikesan oleh HttpClient , tetapi kerana kami mematikan arahan pengalihan automatik, ia tidak lagi berlaku.

Langkah terakhir dalam mekanisme pengembangan URL adalah mengesan gelung pengalihan dan gagal dengan cepat sekiranya gelung seperti itu terjadi.

Agar ini berkesan, kami memerlukan beberapa maklumat tambahan daripada kaedah expandSingleLevel yang kami tentukan sebelumnya - terutamanya, kami juga perlu mengembalikan kod status respons bersama dengan URL.

Oleh kerana java tidak menyokong beberapa nilai pulangan, kami akan membungkus maklumat dalam objek org.apache.commons.lang3.tuple.Pair - tandatangan kaedah baru sekarang ialah:

public Pair expandSingleLevelSafe(String url) throws IOException {

Dan akhirnya, mari sertakan pengesanan kitaran pengalihan dalam mekanisme pengembangan utama:

public String expandSafe(String urlArg) throws IOException { String originalUrl = urlArg; String newUrl = expandSingleLevelSafe(originalUrl).getRight(); List alreadyVisited = Lists.newArrayList(originalUrl, newUrl); while (!originalUrl.equals(newUrl)) { originalUrl = newUrl; Pair statusAndUrl = expandSingleLevelSafe(originalUrl); newUrl = statusAndUrl.getRight(); boolean isRedirect = statusAndUrl.getLeft() == 301 || statusAndUrl.getLeft() == 302; if (isRedirect && alreadyVisited.contains(newUrl)) { throw new IllegalStateException("Likely a redirect loop"); } alreadyVisited.add(newUrl); } return newUrl; }

Dan hanya itu - mekanisme expandSafe dapat menguraikan URL melalui sebilangan perkhidmatan pemendekan URL yang sewenang-wenangnya, sementara gagal dengan pantas pada gelung pengalihan.

5. Kesimpulan

Tutorial ini membincangkan cara mengembangkan URL pendek di java - menggunakan Apache HttpClient .

Kami memulakan dengan penggunaan pengguna yang sederhana dengan URL yang hanya dipersingkat sekali, dan kemudian menerapkan mekanisme yang lebih generik, yang mampu menangani pelbagai peringkat pengalihan dan mengesan gelung pengalihan dalam prosesnya.

Pelaksanaan contoh-contoh ini dapat dijumpai dalam projek github - ini adalah projek berasaskan Eclipse, jadi mudah untuk diimport dan dijalankan sebagaimana adanya.