Перейти к основному содержанию
`Ctrl`+`K`

# Работа с HTTP-запросами

Для отправки HTTP-запроса и обработки полученного ответа предусмотрен класс `Btk_HttpPkg`.

Доступна настройка конфигурации запроса `RequestConfig`, создание запроса `HttpRequest` с необходимым методом, заполнение тела запроса, обработка полученного овтета `HttpResult`.

## Конфигурация и отправка запроса, обработка ответа

### Построение запроса

Пример Get-запроса:

    Btk_HttpPkg().get("https://httpbin.org/status/200".ns)
      .configAppend(_.setConnectTimeout(10000))
      .configAppend(_.setMaxRedirects(3))
      .headers(("key".ns, "value".ns))
      .basicAuth("login".ns, "password".ns)
      .build()
      .process(response => {
        print(response.getStatusLine.getStatusCode)
        EntityUtils.consume(response.getEntity)
      })
      .get

- `get()`, `post()` и прочие — создание запроса с нужным методом.

- `configAppend()` — задаёт свойства конфигурации запроса.

- `headers()` — для установки заголовков.

- `basicAuth()` или `bearerAuth()` — для установки данных аутентификации.

- `build()` — переход к обработчикам результата.

### Установка тела запроса. Отправка и получение JSON

Для Post-запроса есть возможность установки тела запроса с нужным типом содержимого с помощью методов:

- `setEntity(entity: HttpEntity)`

- `setStringEntity(body: NString)`

- `setJSONEntity(body: NString)`

- `setXMLEntity(body: NString)`

Пример запроса, передающего и получающего JSON-объект:

    val svRequestBody = """{ "data": "Some Data Sample" }"""
    val jvResponseBody = Btk_HttpPkg().post("https://httpbin.org/anything".ns)
      .setJSONEntity(svRequestBody)
      .build()
      .getJObject()
      .get
    print(jvResponseBody)

## Обработка результата

### Метод process

- С помощью лямбды HttpResponse -> T.

- Реализовав интерфейс `org.apache.http.client.ResponseHandler`.

- Реализовав интерфейс `org.apache.http.impl.client.AbstractResponseHandler` (Автоматическое формирование ошибок при http статусе >= 300).

Внимание

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

1. Ручным закрытием response.getEntity.getContent.close().

2. Передачей response.getEntity.getContent в методы которые сами закрывают InputStream.

3. Вызовом EntityUtils.consume(response.getEntity).

### Готовые обработчики

Также, помимо `process()`, к использованию доступны следующие методы для получения ответа:

- `execute()` — выполнить запрос и вернуть `Try[Unit]`.

- `getText()` — тело ответа в виде строки. `Try[NString]`.

- `getJObject()` — ответ в виде `Try[JObject]`.

- `getJArray()` — ответ в виде `Try[JArray]`.

- `forStream[T](f: InputStream => T)` — обработать `InputStream`, полученный из содержимого ответа.

## Обработка ошибок

Пример обработки ответа с ошибкой:

    try app {
      val jvResponseBody = Btk_HttpPkg().post("https://httpbin.org/json".ns)
        .basicAuth("login".ns, "password".ns)
        .setStringEntity("data")
        .build()
        .getJObject() match {
          // HttpResponseException если были использованы готовые обработчики или основанный на `HttpResponseException`.
          case Failure(ex: HttpResponseException) if ex.getStatusCode == 401 =>
            throw AppException(s"Ошибка ответа на запрос. Код: ${ex.getStatusCode}. Причина: Неверный логин или пароль.")
          case Failure(ex: HttpResponseException) if ex.getStatusCode == 405 =>
            throw AppException(s"Ошибка ответа на запрос. Код: ${ex.getStatusCode}. Причина: Использование недопустимого метода.")
          // Ошибки обработки, socket timeout и тп
          case Failure(ex) => throw ex
          case Success(jObj) => jObj
        }
      print(jvResponseBody)
    }