1. Обзор
В этом кратком руководстве показано, как настроить Apache HttpClient для автоматического следования перенаправлениям для запросов POST.
Если вы хотите копнуть глубже и узнать о других интересных вещах, которые можно делать с помощью HttpClient, — перейдите к основному руководству по HttpClient .
По умолчанию автоматически выполняются только запросы GET, приводящие к перенаправлению. Если на запросы POST отвечает либо HTTP 301 Moved Permanently
, либо 302 Found
, перенаправление не выполняется автоматически .
Это указано в HTTP RFC 2616 :
Если код состояния 301 получен в ответ на запрос, отличный от GET или HEAD, пользовательский агент НЕ ДОЛЖЕН автоматически перенаправлять запрос, если он не может быть подтвержден пользователем, поскольку это может изменить условия, при которых был выдан запрос.
Конечно, есть случаи, когда нам нужно изменить это поведение и ослабить строгую спецификацию HTTP.
Во-первых, давайте проверим поведение по умолчанию:
@Test
public void givenPostRequest_whenConsumingUrlWhichRedirects_thenNotRedirected()
throws ClientProtocolException, IOException {
HttpClient instance = HttpClientBuilder.create().build();
HttpResponse response = instance.execute(new HttpPost("http://t.co/I5YYd9tddw"));
assertThat(response.getStatusLine().getStatusCode(), equalTo(301));
}
Как видите, перенаправление по умолчанию не выполняется , и мы получаем код состояния 301
.
2. Перенаправление на HTTP POST
2.1. Для HttpClient 4.3 и выше
В HttpClient 4.3 был введен API более высокого уровня как для создания, так и для настройки клиента:
@Test
public void givenRedirectingPOST_whenConsumingUrlWhichRedirectsWithPOST_thenRedirected()
throws ClientProtocolException, IOException {
HttpClient instance =
HttpClientBuilder.create().setRedirectStrategy(new LaxRedirectStrategy()).build();
HttpResponse response = instance.execute(new HttpPost("http://t.co/I5YYd9tddw"));
assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
}
Обратите внимание , что HttpClientBuilder
теперь является отправной точкой гибкого API , который позволяет выполнять полную настройку клиента более читабельным способом, чем раньше.
2.2. Для HTTP-клиента 4.2
В предыдущей версии HttpClient (4.2) мы могли настроить стратегию перенаправления прямо на клиенте:
@SuppressWarnings("deprecation")
@Test
public void givenRedirectingPOST_whenConsumingUrlWhichRedirectsWithPOST_thenRedirected()
throws ClientProtocolException, IOException {
DefaultHttpClient client = new DefaultHttpClient();
client.setRedirectStrategy(new LaxRedirectStrategy());
HttpResponse response = client.execute(new HttpPost("http://t.co/I5YYd9tddw"));
assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
}
Обратите внимание, что теперь, с новой LaxRedirectStrategy
, ограничения HTTP ослаблены, а перенаправление также выполняется через POST, что приводит к коду состояния 200 OK .
2.3. Предварительно HttpClient 4.2
До HttpClient 4.2 класса LaxRedirectStrategy
не существовало, поэтому нам нужно создать свой собственный:
@Test
public void givenRedirectingPOST_whenConsumingUrlWhichRedirectsWithPOST_thenRedirected()
throws ClientProtocolException, IOException {
DefaultHttpClient client = new DefaultHttpClient();
client.setRedirectStrategy(new DefaultRedirectStrategy() {
/** Redirectable methods. */
private String[] REDIRECT_METHODS = new String[] {
HttpGet.METHOD_NAME, HttpPost.METHOD_NAME, HttpHead.METHOD_NAME
};
@Override
protected boolean isRedirectable(String method) {
for (String m : REDIRECT_METHODS) {
if (m.equalsIgnoreCase(method)) {
return true;
}
}
return false;
}
});
HttpResponse response = client.execute(new HttpPost("http://t.co/I5YYd9tddw"));
assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
}
3. Заключение
В этом кратком руководстве показано, как настроить любую версию Apache HttpClient для выполнения перенаправлений и для HTTP-запросов POST, тем самым ослабив строгий стандарт HTTP.
Реализацию всех этих примеров и фрагментов кода можно найти в моем проекте на github — это проект на основе Eclipse, поэтому его легко импортировать и запускать как есть.