Ktor Client — HTTP-запросы
Ktor Client
Сервер Ktor принимает HTTP-запросы. Ktor Client — библиотека, которая эти запросы отправляет из приложения: Desktop, Android, backend-утилита. Оба используют корутины: вызовы get / post — suspend-функции.
Типичная цепочка: ViewModel → HttpClient → JSON → список на экране (Compose, Flow).
Словарь терминов
| Термин | Простыми словами |
|---|---|
| HTTP-клиент | Программа, которая формирует запрос (метод, URL, заголовки, тело) и читает ответ. |
| GET | «Дай данные» — обычно без тела. |
| POST | «Создай / отправь данные» — часто с JSON в теле. |
| HttpClient | Главный объект Ktor Client; создаётся один раз на приложение. |
| Engine (CIO, OkHttp) | Низкоуровневая реализация сокетов под платформу. |
| Content Negotiation | Автоматический JSON ↔ Kotlin-объект. |
| Suspend-вызов | client.get(...) можно вызывать только из корутины. |
Зависимости (JVM)
build.gradle.kts:
plugins {
kotlin("jvm") version "1.9.24"
kotlin("plugin.serialization") version "1.9.24"
application
}
dependencies {
implementation("io.ktor:ktor-client-core:2.3.12")
implementation("io.ktor:ktor-client-cio:2.3.12")
implementation("io.ktor:ktor-client-content-negotiation:2.3.12")
implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.12")
implementation("io.ktor:ktor-client-logging:2.3.12")
}
На Android вместо cio часто подключают ktor-client-okhttp.
Модель данных
Те же классы, что на сервере в 221.md:
import kotlinx.serialization.Serializable
@Serializable
data class Note(val id: Int, val text: String)
@Serializable
data class NoteCreate(val text: String)
Создание клиента
import io.ktor.client.*
import io.ktor.client.engine.cio.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.client.plugins.logging.*
import io.ktor.serialization.kotlinx.json.*
import kotlinx.serialization.json.Json
val client = HttpClient(CIO) {
install(ContentNegotiation) {
json(Json { ignoreUnknownKeys = true })
}
install(Logging) {
level = LogLevel.INFO
}
}
| Настройка | Зачем |
|---|---|
ContentNegotiation + json() | Тело ответа → Note, объект → JSON в POST |
ignoreUnknownKeys = true | Сервер добавил поле — клиент со старой моделью не падает |
Logging | В консоль: URL, статус, время (отладка) |
Важно: HttpClient дорогой в создании — один экземпляр на приложение (singleton, DI). При завершении: client.close().
GET и POST — разбор
Предположим, сервер из 221.md слушает http://127.0.0.1:8080.
import io.ktor.client.call.*
import io.ktor.client.request.*
import io.ktor.http.*
import kotlinx.coroutines.runBlocking
suspend fun demo(client: HttpClient) {
val health: Map<String, String> = client.get("http://127.0.0.1:8080/health").body()
println(health)
val notes: List<Note> = client.get("http://127.0.0.1:8080/notes").body()
println("Заметок: ${notes.size}")
val created: Note = client.post("http://127.0.0.1:8080/notes") {
contentType(ContentType.Application.Json)
setBody(NoteCreate("Из клиента"))
}.body()
println("Создано: ${created.id} — ${created.text}")
}
fun main() = runBlocking {
val client = HttpClient(CIO) {
install(ContentNegotiation) { json() }
}
try {
demo(client)
} finally {
client.close()
}
}
Построчно:
| Строка | Что происходит |
|---|---|
client.get(url) | HTTP GET, suspend до ответа |
.body<Map<...>>() | Десериализация JSON в тип |
post(url) { ... } | Блок настраивает запрос |
contentType(Application.Json) | Заголовок Content-Type: application/json |
setBody(NoteCreate(...)) | Сериализация объекта в JSON-тело |
runBlocking | Только для main; в Android — viewModelScope.launch |
Обработка ошибок
import io.ktor.client.plugins.*
suspend fun safeGet(client: HttpClient, url: String): String? =
try {
client.get(url).body()
} catch (e: ClientRequestException) {
println("HTTP ${e.response.status}: ${e.response.status.description}")
null
} catch (e: ServerResponseException) {
println("Ошибка сервера: ${e.response.status}")
null
}
| Исключение | Когда |
|---|---|
ClientRequestException | 4xx — ошибка запроса (404, 401) |
ServerResponseException | 5xx — ошибка сервера |
Таймаут в блоке клиента:
HttpClient(CIO) {
engine {
requestTimeout = 10_000
}
}
Заголовки и токен
client.get("https://api.example.com/profile") {
header(HttpHeaders.Authorization, "Bearer $token")
parameter("page", 1)
}
parameter добавляет ?page=1 к URL. Плагин Auth может подставлять токен автоматически для серии запросов.
Android и Kotlin Multiplatform
| Платформа | Движок |
|---|---|
| JVM / Desktop | CIO |
| Android | OkHttp |
| iOS | Darwin |
В KMP: expect fun createHttpClient(): HttpClient в commonMain, actual в androidMain / iosMain — сеть в общем коде, движок под платформу.
Частые ошибки
| Симптом | Причина |
|---|---|
Connection refused | Сервер не запущен |
| Serialization error | Нет @Serializable или разные поля JSON |
| Вызов из UI-потока без корутины | Нужен launch + suspend |
| Утечки | Клиент не close() при выходе из процесса |
Связанные материалы
См. также
Другие статьи этого же раздела в боковом меню (как на странице «О разделе»). История Kotlin - создание языка JetBrains для плавной совместимости с Java и современной разработки. Экосистема Kotlin-приложений - инструменты, фреймворки и мультиплатформенные сценарии разработки. Kotlin — это современный язык программирования общего назначения, который работает на платформе Java Virtual Machine (JVM), а также компилируется в JavaScript или нативный код. Набор советов, правил, принципов и обычаев в разработке на этом языке. Основы Kotlin - архитектура проекта, платформенные модули и базовые принципы разработки на языке. Типизация, набор правил определения типа данных значений языка. Операторы и выражения в Kotlin - логика вычислений, приоритеты операций и идиоматичный стиль записи условий. Циклы и управляющие конструкции в Kotlin - идиоматичные способы итерации, условия и управление выполнением. ООП в Kotlin - классы, модификаторы доступа, наследование и идиоматичное проектирование объектных структур. Кавычки, точки, запятые, скобки и прочие знаки препинания. Kotlin использует набор зарезервированных слов для построения синтаксических конструкций языка. Все ключевые слова разделены на категории по назначению. Набор функций, которые включены в стандартную библиотеку языка.История языка Kotlin
Экосистема Kotlin-приложений
Что требуется знать перед началом изучения языка программирования Kotlin
Рекомендации по разработке на Kotlin
Основы языка Kotlin
Типы данных и объявление переменных
Операторы и выражения в Kotlin
Циклы и управляющие конструкции
Объектно-ориентированное программирование в Kotlin
Синтаксис и пунктуация в Kotlin
Ключевые слова языка Kotlin
Встроенные функции и расширения Kotlin