Премахнете съкращението на URL адресите с HttpClient

1. Общ преглед

В тази статия ще покажем как да премахнете съкращението на URL адреси с помощта на HttpClient .

Един прост пример е, когато оригиналния URL адреса е бил съкратен веднъж - от услуга като bit.ly .

По-сложен пример е, когато URL адресът е бил съкращаван многократно от различни такива услуги и са необходими множество проходи, за да стигнете до оригиналния пълен URL адрес.

Ако искате да копаете по-дълбоко и да научите други страхотни неща, които можете да направите с HttpClient - преминете към основния урок за HttpClient .

2. Премахнете съкращението на URL адреса веднъж

Нека започнем просто - премахнете съкращението на URL адрес, който е преминал само веднъж през услуга за съкращаване на URL адреси.

Първото нещо, от което се нуждаем, е http клиент, който не следва автоматично пренасочвания :

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

Това е необходимо, защото ще трябва ръчно да прихванем отговора за пренасочване и да извлечем информация от него.

Започваме с изпращане на заявка до съкратения URL адрес - отговорът, който получаваме, ще бъде 301 Moved Permanently .

След това трябва да извлечем заглавката на местоположението, сочеща към следващия и в този случай - краен URL адрес:

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

И накрая, прост тест на живо, разширяващ URL:

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

3. Обработвайте няколко нива на URL

Проблемът с кратките URL адреси е, че те могат да бъдат съкращавани многократно от съвсем различни услуги. Разширяването на такъв URL адрес ще изисква многократни проходи, за да стигнете до оригиналния URL адрес.

Ще приложим примитивната операция expandSingleLevel , дефинирана по-рано, за да просто прегледаме всички посреднически URL адреси и да стигнем до крайната цел :

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

Сега, с новия механизъм за разширяване на множество нива на URL адреси, нека дефинираме тест и приложим това да работи:

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

Този път краткият URL - //t.co/e4rDDbnzmk - който всъщност се съкращава два пъти - веднъж чрез bit.ly и втори път чрез услугата t.co - е правилно разширен до оригиналния URL адрес.

4. Откриване на цикли за пренасочване

И накрая, някои URL адреси не могат да бъдат разширени, защото образуват цикъл за пренасочване. Този тип проблем ще бъде открит от HttpClient , но тъй като изключихме автоматичното проследяване на пренасочванията, той вече не го прави.

Последната стъпка в механизма за разширяване на URL ще бъде откриването на цикли за пренасочване и бързо неуспешно, в случай че възникне такъв цикъл.

За да бъде това ефективно, се нуждаем от допълнителна информация от метода expandSingleLevel , който дефинирахме по-рано - главно трябва да върнем и кода на състоянието на отговора заедно с URL адреса.

Тъй като java не поддържа множество връщани стойности, ще обгърнем информацията в обект org.apache.commons.lang3.tuple.Pair - новият подпис на метода вече ще бъде:

public Pair expandSingleLevelSafe(String url) throws IOException {

И накрая, нека включим откриването на цикъла за пренасочване в основния механизъм за разширяване:

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

И това е всичко - механизмът expandSafe е в състояние да премахне съкращението на URL, преминавайки през произволен брой услуги за съкращаване на URL адреси, като същевременно правилно се проваля бързо при цикли за пренасочване.

5. Заключение

Този урок обсъди как да разширите кратки URL адреси в java - използвайки Apache HttpClient .

Започнахме с проста употреба с URL адрес, който се съкращава само веднъж и след това внедрихме по-общ механизъм, способен да обработва множество нива на пренасочвания и да открива цикли на пренасочване в процеса.

Изпълнението на тези примери може да бъде намерено в проекта github - това е проект, базиран на Eclipse, така че трябва да е лесно да се импортира и да се изпълнява както е.