[содержание](/readme.md)  

# Http запросы

В Kotlin-е есть встроенные функции работы с http-запросами, но стандартный код для сетевых запросов сложен, излишен и в реальном мире почти не используется. Используются библиотеки. Самые популярные: OkHttp, Fuel и Retrofit.

Мы рассмотрим работу с http на примере библиотеки [Fuel](https://github.com/kittinunf/fuel).

## Установка библиотеки

1. В зависимости приложения добавляем (что такое зависимости и куда их добавлять мы рассмотрим в теме про работу с IDE): 

```
implementation 'com.github.kittinunf.fuel:fuel-android:2.2.1' 
```

> актуальную версию библиотеки уточняйте на сайте разработчика

2. В секцию импорта добавить ``import com.github.kittinunf.result.Result``.

## Примеры запросов

Запросы бывают двух типов: синхронные (приложение ждет ответа от сервера, останавливая работу) и асинхронные (запрос посылается в фоне, выполнение программы продолжается - такой режим предпочтительнее, т.к. не "замораживает" интерфейс). Но мы с вами уже знаем, что существуют корутины и мы любой синхронный код можем запустить асинхронно, поэтому дальше будем рассматривать синхронный код.

Запрос можно сформировать через фабричные методы класса Fuel:

```kt
Fuel.get(...)
Fuel.post(...)
// полный список доступных методов см. на сайте библиотеки, нам достаточно этих двух
```

Или через расширение объекта String:

```kt
"http://адрес.сайта".httpGet()
"http://адрес.сайта".httpPost()
```

Далее рассматривается авторизация на тестовом сервисе:

> Вариантов авторизации существует множество, далее рассмотрен вариант, который использовался в демо-экзамене на курсах "Мастера 5000"

**Алгоритм авторизации**:

* при любом запросе (кроме login и logout) должен добавляться параметр token
если токен не найден, то вернется сообщение, что пользователь не авторизован: 
  ```json
  {"notice":{"answer": "user not authorized"}}
  ```

* для получения токена необходимо послать **post** запрос на URL */login* с параметрами login и password (в качестве логина используйте *ИФамилия* в латинской транскрипции, т.е. Евгений колесников = EKolesnikov. Пароль любой)

* если токен уже был получен, то сервер вернет ошибку 
  ```json
  {"notice":{"answer": "User is active"}}
  ```
  в этом случае нужно разлогиниться (послать запрос с теми же параметрами на URL */logout*)

* при успешной авторизации сервер вернет токен: 
  ```json
  {"notice": {"token":123}
  ```

> Адрес тестового сервера уточняйте в начале работы

```kt
import com.github.kittinunf.fuel.Fuel
import com.github.kittinunf.result.Result

fun main() {
    // здесь УРЛ другого сервиса, при тестировании авторизации вставляйте свой
    val URL = "https://httpbin.org"
    val (_, _, result) = Fuel
        .post(
            "$URL/post",                        // путь тоже должен быть другой
            listOf( "login" to "EKolesnikov",   // в массиве передаются параметры запроса
                    "password" to "123456"))
        .responseString()

    // разбираем результат
    when (result) {
        is Result.Failure -> {
            // на ошибку лучше выбросить исключение
            println( result.getException().toString() )
        }
        is Result.Success -> {
            // тут реализуете разбор полученного ответа
            println( result.get() )
        }
    }
}
```

На этот запрос придет примерно такой ответ:

```json
{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "login": "EKolesnikov", 
    "password": "123456"
  }, 
  "headers": {
    "Accept": "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2", 
    "Content-Length": "33", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "httpbin.org", 
    "User-Agent": "Java/11.0.5", 
    "X-Amzn-Trace-Id": "Root=1-5e3d990d-f0d25f92f87cec3612db9f75"
  }, 
  "json": null, 
  "origin": "888.888.888.888", 
  "url": "https://httpbin.org/post"
}
```

Тут, как и в ответе сервиса, данные в формате JSON.

## JSON

JSON (JavaScript Object Notation) - простой формат обмена данными, удобный для чтения и написания как человеком, так и компьютером. JSON - текстовый формат, полностью независимый от языка реализации.

JSON основан на двух структурах данных:

* Коллекция пар ключ/значение. В разных языках, эта концепция реализована как объект, запись, структура, словарь, хэш, именованный список или ассоциативный массив.

  ```json
  "login":"EKolesnikov"
  ```

* Упорядоченный список значений. В большинстве языков это реализовано как массив, вектор, список или последовательность.

  ```json
  [1,2,3]
  ```

Это универсальные структуры данных. Почти все современные языки программирования поддерживают их в какой-либо форме. Логично предположить, что формат данных, независимый от языка программирования, должен быть основан на этих структурах.

Подробное описание можете посмотреть в интернете, для нас достаточно знание следующих типов:

* *"литерал"* - в двойных кавычках строка в формате UTF-8, строка может быть как ключем, так и значением:
  ```json
  "login":"EKolesnikov"
  ```

* *{объект}* - неупорядоченный набор пар ключ:значение, причем значением может быть любой другой тип. Пары разделяются запятыми:
  ```json
  {"login":"EKolesnikov", "value": 1, "object": {...}, "array": [...]}
  ```

* *[массив]* - упорядоченная коллекция значений. Значения разделены запятой. Значением может быть любой другой тип.

  ```json
  ["login", 1, {...}, [...], null, true]
  ```

* *числа* - числа пишутся без кавычек, могут быть как ключем (не уверен - проверить), так и значением. Дробная часть обозначается точкой:

  ```json
  "int": 123, "float": 12.34
  ```

* логические константы и null:

  ```json
  true, false, null
  ```

Для работы с JSON в котлине есть типы JSON

[содержание](/readme.md)  
