Annulla accorciamento degli URL con HttpClient

1. Panoramica

In questo articolo mostreremo come annullare l'abbreviazione di un URL utilizzando HttpClient .

Un semplice esempio è quando l'URL originale è stato ridotto una volta - da un servizio come bit.ly .

Un esempio più complesso è quando l'URL è stato accorciato più volte da diversi servizi di questo tipo e sono necessari più passaggi per arrivare all'URL completo originale.

Se vuoi approfondire e imparare altre cose interessanti che puoi fare con HttpClient, vai al tutorial principale di HttpClient .

2. Annulla l'accorciamento dell'URL una volta

Iniziamo in modo semplice: annulla l'accorciamento di un URL che è stato passato solo una volta attraverso un servizio di abbreviazione URL.

La prima cosa di cui abbiamo bisogno è un client http che non segua automaticamente i reindirizzamenti :

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

Ciò è necessario perché dovremo intercettare manualmente la risposta di reindirizzamento ed estrarre informazioni da essa.

Iniziamo inviando una richiesta all'URL abbreviato: la risposta che riceviamo sarà 301 Spostato permanentemente .

Quindi, dobbiamo estrarre l' intestazione Location che punta al successivo e, in questo caso, l'URL finale:

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

Infine, un semplice test dal vivo che espande un URL:

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

3. Elaborare più livelli di URL

Il problema con gli URL brevi è che possono essere abbreviati più volte , da servizi completamente diversi. L'espansione di un URL di questo tipo richiederà più passaggi per raggiungere l'URL originale.

Stiamo per applicare l'expandSingleLevel operazione primitiva definito in precedenza semplicemente scorrere tutti l'URL intermediario e ottenere al bersaglio finale :

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

Ora, con il nuovo meccanismo di espansione di più livelli di URL, definiamo un test e mettiamolo in pratica:

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

Questa volta, l'URL breve - //t.co/e4rDDbnzmk - che in realtà è stato accorciato due volte - una volta tramite bit.ly e una seconda volta tramite il servizio t.co - viene correttamente espanso all'URL originale.

4. Rileva sui loop di reindirizzamento

Infine, alcuni URL non possono essere espansi perché formano un loop di reindirizzamento. Questo tipo di problema verrebbe rilevato da HttpClient , ma poiché abbiamo disattivato il follow automatico dei reindirizzamenti, non lo fa più.

Il passaggio finale nel meccanismo di espansione dell'URL sarà il rilevamento dei loop di reindirizzamento e il fallimento rapido nel caso in cui si verifichi un tale loop.

Affinché ciò sia efficace, abbiamo bisogno di alcune informazioni aggiuntive dal metodo expandSingleLevel che abbiamo definito in precedenza - principalmente, dobbiamo restituire anche il codice di stato della risposta insieme all'URL.

Poiché java non supporta più valori di ritorno, racchiuderemo le informazioni in un oggetto org.apache.commons.lang3.tuple.Pair : la nuova firma del metodo sarà ora:

public Pair expandSingleLevelSafe(String url) throws IOException {

Infine, includiamo il rilevamento del ciclo di reindirizzamento nel meccanismo di espansione principale:

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

E questo è tutto: il meccanismo expandSafe è in grado di annullare l'accorciamento dell'URL passando attraverso un numero arbitrario di servizi di accorciamento degli URL, mentre fallisce correttamente nei cicli di reindirizzamento.

5. conclusione

Questo tutorial ha discusso come espandere URL brevi in ​​java , utilizzando Apache HttpClient .

Abbiamo iniziato con un semplice caso d'uso con un URL che viene accorciato una sola volta, quindi abbiamo implementato un meccanismo più generico, in grado di gestire più livelli di reindirizzamenti e rilevare i loop di reindirizzamento nel processo.

L'implementazione di questi esempi può essere trovata nel progetto github: questo è un progetto basato su Eclipse, quindi dovrebbe essere facile da importare ed eseguire così com'è.