Рубрики
Без рубрики

Не сокращенные URL-адреса с помощью HttpClient

Как удалить URL – адреса в Java-настроить и использовать HttpClient для расширения URL-адресов и обнаружения циклов перенаправления.

Автор оригинала: Eugen Paraschiv.

1. Обзор

В этой статье мы покажем, как сократить URL-адреса с помощью |/HttpClient .

Простой пример-это когда исходный URL-адрес был сокращен один раз – службой, такой как bit.лы .

Более сложный пример-это когда URL-адрес был сокращен несколько раз различными такими службами , и требуется несколько проходов, чтобы добраться до исходного полного URL-адреса.

Если вы хотите копнуть глубже и узнать другие интересные вещи, которые вы можете сделать с помощью HttpClient – перейдите к основному учебнику HttpClient .

2. Один раз откорректируйте URL-адрес

Давайте начнем с простого – разрежьте URL-адрес, который был передан через службу сокращения URL-адресов только один раз.

Первое, что нам понадобится, – это http-клиент, который не будет автоматически следовать перенаправлениям :

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

Это необходимо, потому что нам нужно будет вручную перехватить ответ на перенаправление и извлечь из него информацию.

Мы начинаем с отправки запроса на сокращенный URL – адрес-ответ, который мы получим, будет 301 Перемещен навсегда .

Затем нам нужно извлечь Местоположение заголовок , указывающий на следующий, и в этом случае – окончательный 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("http://bit.ly/13jEoS1");
    assertThat(actualResult, equalTo(expectedResult));
}

3. Обработка Нескольких Уровней URL-Адресов

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

Мы собираемся применить развернуть одноуровневую примитивную операцию, определенную ранее, чтобы просто перебрать все промежуточные 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("http://t.co/e4rDDbnzmk");
    assertThat(actualResult, equalTo(expectedResult));
}

На этот раз короткий URL – адрес – http://t.co/e4rDDbnzmk – который на самом деле сокращается дважды – один раз через бит.ly и во второй раз через t.co сервис – правильно расширен до исходного URL-адреса.

4. Обнаружение в циклах перенаправления

Наконец, некоторые URL-адреса не могут быть расширены, поскольку они образуют цикл перенаправления. Этот тип проблемы будет обнаружен HttpClient , но поскольку мы отключили автоматическое отслеживание перенаправлений, он больше не работает.

Последним шагом в механизме расширения URL-адресов будет обнаружение циклов перенаправления и быстрый сбой в случае возникновения такого цикла.

Чтобы это было эффективно, нам нужна дополнительная информация из метода expandSingleLevel , который мы определили ранее – в основном, нам также нужно вернуть код состояния ответа вместе с URL-адресом.

Поскольку java не поддерживает несколько возвращаемых значений, мы собираемся обернуть информацию в org.apache.commons.lang3.tuple.Pair object – теперь новая сигнатура метода будет:

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, поэтому его должно быть легко импортировать и запускать как есть.