Перейти к основному содержимому

Путеводитель по Юниресту

· 5 мин. чтения

1. Обзор

Unirest — это облегченная клиентская библиотека HTTP от Mashape. Наряду с Java он также доступен для Node.js, .Net, Python, Ruby и т. д.

Прежде чем мы начнем, обратите внимание, что здесь мы будем использовать mocky.io для всех наших HTTP-запросов.

2. Настройка Мавена

Для начала давайте сначала добавим необходимые зависимости:

<dependency>
<groupId>com.mashape.unirest</groupId>
<artifactId>unirest-java</artifactId>
<version>1.4.9</version>
</dependency>

Ознакомьтесь с последней версией здесь .

3. Простые запросы

Давайте отправим простой HTTP-запрос, чтобы понять семантику фреймворка:

@Test
public void shouldReturnStatusOkay() {
HttpResponse<JsonNode> jsonResponse
= Unirest.get("http://www.mocky.io/v2/5a9ce37b3100004f00ab5154")
.header("accept", "application/json").queryString("apiKey", "123")
.asJson();

assertNotNull(jsonResponse.getBody());
assertEquals(200, jsonResponse.getStatus());
}

Обратите внимание, что API работает плавно, эффективно и довольно легко читается.

Мы передаем заголовки и параметры с помощью API header() и fields() .

И запрос вызывается при вызове метода asJson() ; у нас также есть другие опции, такие как asBinary(), asString() и asObject().

Чтобы передать несколько заголовков или полей, мы можем создать карту и передать их в .headers(Map<String, Object> заголовки) и .fields(Map<String, String> поля) соответственно:

@Test
public void shouldReturnStatusAccepted() {
Map<String, String> headers = new HashMap<>();
headers.put("accept", "application/json");
headers.put("Authorization", "Bearer 5a9ce37b3100004f00ab5154");

Map<String, Object> fields = new HashMap<>();
fields.put("name", "Sam ForEach");
fields.put("id", "PSP123");

HttpResponse<JsonNode> jsonResponse
= Unirest.put("http://www.mocky.io/v2/5a9ce7853100002a00ab515e")
.headers(headers).fields(fields)
.asJson();

assertNotNull(jsonResponse.getBody());
assertEquals(202, jsonResponse.getStatus());
}

3.1. Передача параметров запроса

Чтобы передать данные в виде строки запроса , мы будем использовать метод queryString() :

HttpResponse<JsonNode> jsonResponse 
= Unirest.get("http://www.mocky.io/v2/5a9ce37b3100004f00ab5154")
.queryString("apiKey", "123")

3.2. Использование параметров пути

Для передачи любых параметров URL мы можем использовать метод routeParam() :

HttpResponse<JsonNode> jsonResponse 
= Unirest.get("http://www.mocky.io/v2/5a9ce37b3100004f00ab5154/{userId}")
.routeParam("userId", "123")

Имя заполнителя параметра должно совпадать с первым аргументом метода.

3.3. Запросы с телом

Если для нашего запроса требуется тело строки/JSON, мы передаем его с помощью метода body() :

@Test
public void givenRequestBodyWhenCreatedThenCorrect() {

HttpResponse<JsonNode> jsonResponse
= Unirest.post("http://www.mocky.io/v2/5a9ce7663100006800ab515d")
.body("{\"name\":\"Sam ForEach\", \"city\":\"viena\"}")
.asJson();

assertEquals(201, jsonResponse.getStatus());
}

3.4. Картограф объектов

Чтобы использовать asObject() или body() в запросе, нам нужно определить наш преобразователь объектов. Для простоты мы будем использовать средство сопоставления объектов Джексона.

Давайте сначала добавим в pom.xml следующие зависимости :

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.4</version>
</dependency>

Всегда используйте последнюю версию Maven Central .

Теперь давайте настроим наш маппер:

Unirest.setObjectMapper(new ObjectMapper() {
com.fasterxml.jackson.databind.ObjectMapper mapper
= new com.fasterxml.jackson.databind.ObjectMapper();

public String writeValue(Object value) {
return mapper.writeValueAsString(value);
}

public <T> T readValue(String value, Class<T> valueType) {
return mapper.readValue(value, valueType);
}
});

Обратите внимание, что setObjectMapper() следует вызывать только один раз для установки картографа; как только экземпляр картографа установлен, он будет использоваться для всех запросов и ответов.

Давайте теперь протестируем новую функциональность, используя пользовательский объект Article :

@Test
public void givenArticleWhenCreatedThenCorrect() {
Article article
= new Article("ID1213", "Guide to Rest", "foreach");
HttpResponse<JsonNode> jsonResponse
= Unirest.post("http://www.mocky.io/v2/5a9ce7663100006800ab515d")
.body(article)
.asJson();

assertEquals(201, jsonResponse.getStatus());
}

4. Методы запроса

Подобно любому HTTP-клиенту, платформа предоставляет отдельные методы для каждого HTTP-глагола:

ПОЧТА:

Unirest.post("http://www.mocky.io/v2/5a9ce7663100006800ab515d")

ПОМЕЩАТЬ:

Unirest.put("http://www.mocky.io/v2/5a9ce7663100006800ab515d")

ПОЛУЧИТЬ:

Unirest.get("http://www.mocky.io/v2/5a9ce7663100006800ab515d")

УДАЛИТЬ:

Unirest.delete("http://www.mocky.io/v2/5a9ce7663100006800ab515d")

ПЛАСТЫРЬ:

Unirest.patch("http://www.mocky.io/v2/5a9ce7663100006800ab515d")

ОПЦИИ:

Unirest.options("http://www.mocky.io/v2/5a9ce7663100006800ab515d")

5. Методы ответа

Как только мы получим ответ, давайте проверим код состояния и сообщение о состоянии:

//...
jsonResponse.getStatus()

//...

Извлеките заголовки:

//...
jsonResponse.getHeaders();
//...

Получите тело ответа:

//...
jsonResponse.getBody();
jsonResponse.getRawBody();
//...

Обратите внимание, что getRawBody() возвращает поток не проанализированного тела ответа, тогда как getBody() возвращает проанализированное тело, используя средство сопоставления объектов, определенное в предыдущем разделе.

6. Обработка асинхронных запросов

Unirest также имеет возможность обрабатывать асинхронные запросы — используя java.util.concurrent.Future и методы обратного вызова:

@Test
public void whenAysncRequestShouldReturnOk() {
Future<HttpResponse<JsonNode>> future = Unirest.post(
"http://www.mocky.io/v2/5a9ce37b3100004f00ab5154?mocky-delay=10000ms")
.header("accept", "application/json")
.asJsonAsync(new Callback<JsonNode>() {

public void failed(UnirestException e) {
// Do something if the request failed
}

public void completed(HttpResponse<JsonNode> response) {
// Do something if the request is successful
}

public void cancelled() {
// Do something if the request is cancelled
}
});

assertEquals(200, future.get().getStatus());
}

Интерфейс com.mashape.unirest.http.async.Callback<T> предоставляет три метода: failed() , Cancelled() и Completed ().

Переопределите методы для выполнения необходимых операций в зависимости от ответа.

7. Загрузка файлов

Чтобы загрузить или отправить файл как часть запроса, передайте объект java.io.File как поле с именем файла:

@Test
public void givenFileWhenUploadedThenCorrect() {

HttpResponse<JsonNode> jsonResponse = Unirest.post(
"http://www.mocky.io/v2/5a9ce7663100006800ab515d")
.field("file", new File("/path/to/file"))
.asJson();

assertEquals(201, jsonResponse.getStatus());
}

Мы также можем использовать ByteStream:

@Test
public void givenByteStreamWhenUploadedThenCorrect() {
try (InputStream inputStream = new FileInputStream(
new File("/path/to/file/artcile.txt"))) {
byte[] bytes = new byte[inputStream.available()];
inputStream.read(bytes);
HttpResponse<JsonNode> jsonResponse = Unirest.post(
"http://www.mocky.io/v2/5a9ce7663100006800ab515d")
.field("file", bytes, "article.txt")
.asJson();

assertEquals(201, jsonResponse.getStatus());
}
}

Или используйте входной поток напрямую, добавив ContentType.APPLICATION_OCTET_STREAM в качестве второго аргумента в методе fields() :

@Test
public void givenInputStreamWhenUploadedThenCorrect() {
try (InputStream inputStream = new FileInputStream(
new File("/path/to/file/artcile.txt"))) {

HttpResponse<JsonNode> jsonResponse = Unirest.post(
"http://www.mocky.io/v2/5a9ce7663100006800ab515d")
.field("file", inputStream, ContentType.APPLICATION_OCTET_STREAM, "article.txt").asJson();

assertEquals(201, jsonResponse.getStatus());
}
}

8. Конфигурации Юнирест

Фреймворк также поддерживает типичные конфигурации HTTP-клиента, такие как пул соединений, тайм-ауты, глобальные заголовки и т. д.

Зададим количество подключений и максимальное количество подключений на маршрут:

Unirest.setConcurrency(20, 5);

Настройте тайм-ауты соединения и сокета:

Unirest.setTimeouts(20000, 15000);

Обратите внимание, что значения времени указаны в миллисекундах.

Теперь давайте установим заголовки HTTP для всех наших запросов:

Unirest.setDefaultHeader("X-app-name", "foreach-unirest");
Unirest.setDefaultHeader("X-request-id", "100004f00ab5");

Мы можем очистить глобальные заголовки в любое время:

Unirest.clearDefaultHeaders();

В какой-то момент нам может понадобиться делать запросы через прокси-сервер:

Unirest.setProxy(new HttpHost("localhost", 8080));

Одним из важных аспектов, о котором следует помнить, является корректное закрытие или выход из приложения. Unirest порождает цикл фоновых событий для обработки операций, нам нужно закрыть этот цикл перед выходом из нашего приложения:

Unirest.shutdown();

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

В этом руководстве мы сосредоточились на облегченной клиентской среде HTTP — Unirest. Мы работали с несколькими простыми примерами, как в синхронном, так и в асинхронном режимах.

Наконец, мы также использовали несколько расширенных конфигураций, таких как пул соединений, настройки прокси и т. д.

Как обычно, исходный код доступен на GitHub .