Ktor — це асинхронний HTTP-клієнт для Kotlin, розроблений компанією JetBrains як частина однойменного фреймворку для серверної та клієнтської розробки. Ktor побудований на корутинах Kotlin і підтримує мультиплатформенність. За даними JetBrains, 2025, Ktor забезпечує нативну інтеграцію з Kotlin-екосистемою без рефлексії та додаткових залежностей.
Головне
Ktor — це фреймворк для побудови асинхронних серверних та клієнтських додатків на Kotlin, створений компанією JetBrains. Ktor Client — клієнтська частина фреймворку, що надає HTTP-клієнт з повною підтримкою корутин Kotlin, мультиплатформенності (JVM, Native, JS) та модульної архітектури на плагінах.
Ktor з'явився у 2018 році як альтернатива Retrofit та OkHttp для Kotlin-first проектів. На відміну від Retrofit, який портував Java-підхід з анотаціями, Ktor Client використовує Kotlin DSL для конфігурації запитів — без анотацій та рефлексії. Це робить код більш читабельним та типобезпечним для Kotlin-розробників.
За даними опитування Kotlin Multiplatform 2024, Ktor Client використовується в 35% проектів Kotlin Multiplatform Mobile (KMM), що робить його другим за популярністю HTTP-клієнтом після OkHttp у Kotlin-спільноті. Ktor надають перевагу в проектах, де важлива мультиплатформенність та нативна інтеграція з Kotlin-екосистемою.
Архітектура Ktor Client базується на конвеєрі (pipeline) з плагінів. Кожен запит проходить через послідовність встановлених плагінів, які можуть модифікувати запит, відповідь або виконувати побічні дії — логування, стиснення, серіалізацію, аутентифікацію.
При створенні HTTP-клієнта через HttpClient { } DSL-блоком ви вказуєте двигун (OkHttp, Android, CIO, Darwin) та встановлюєте плагіни. Кожен двигун реалізує низькорівневе відправлення запиту для конкретної платформи: на Android використовується OkHttp-двигун, на iOS — Darwin (URLSession), на Desktop — CIO (Coroutine I/O). HttpClient автоматично вибирає оптимальний двигун для поточної платформи.
Запит у Ktor Client виконується через suspend-функцію, що означає повну інтеграцію з корутинами. Жодних Callback, RxJava або LiveData — лише послідовний код з suspend, який працює асинхронно без блокування потоку.
Конвеєр Ktor складається з фаз: спочатку запит проходить через встановлені плагіни (наприклад, ContentNegotiation для JSON, Logging для логів), потім двигун виконує HTTP-запит, і відповідь знову проходить через плагіни для десеріалізації. Кожен плагін — це suspend-функція, що виконується в корутині конвеєра.
Важлива перевага конвеєра Ktor — можливість умовної обробки. Плагін може перевірити URL або заголовки запиту та пропустити обробку, якщо умова не виконана. Наприклад, ContentEncoding з gzip застосовується лише до відповідей, що містять заголовок Content-Encoding: gzip, а Auth спрацьовує лише для захищених ендпоінтів, не зачіпаючи публічні API.
Такий pipeline-підхід дозволяє комбінувати плагіни гнучко: ви можете встановити ContentNegotiation з JSON, додати Auth з Bearer-токеном, включити стиснення ContentEncoding та HttpTimeout — і всі вони будуть працювати спільно в правильному порядку. Порядок встановлення плагінів має значення: перший встановлений буде обробляти запит раніше за інших.
Плагіни — це модульна система розширення Ktor, що замінює анотації Retrofit та перехоплювачі OkHttp. Кожен плагін вирішує конкретну задачу та встановлюється через функцію install() у блоці HttpClient. Ktor надає вбудовані плагіни, а також дозволяє створювати кастомні.
| Плагін | Призначення |
|---|---|
| ContentNegotiation | Серіалізація та десеріалізація JSON, XML через Kotlinx Serialization |
| Logging | Логування запитів та відповідей з налаштуванням рівня |
| Auth | Аутентифікація: Basic, Bearer, Digest з автоматичним оновленням токена |
| HttpTimeout | Налаштування таймаутів підключення, читання та запиту |
| ContentEncoding | Прозоре стиснення gzip та deflate |
| DefaultRequest | Встановлення значень за замовчуванням для всіх запитів |
Для специфічних завдань створюється кастомний плагін через createClientPlugin. Плагін може перехоплювати запит (onRequest), відповідь (onResponse) або обробляти помилки (onError). Це повністю замінює Interceptor з OkHttp, але з типізованим Kotlin-API та підтримкою suspend-функцій.
Кастомні плагіни зручні для додавання метрик, автоматичної ретрай-логіки, трейсингу запитів або A/B-тестування ендпоінтів. На відміну від перехоплювачів OkHttp, Ktor-плагіни написані на Kotlin та працюють в контексті корутини, що спрощує обробку помилок та таймаутів.
Для налагодження запитів використовується плагін Logging з рівнем ALL, HEADERS або BODY. Logging виводить метод, URL, статус, заголовки та тіло запиту та відповіді. На відміну від HttpLoggingInterceptor з OkHttp, Ktor Logging працює асинхронно та може бути налаштований на фільтрацію за рівнем логу (ERROR, WARN, INFO, DEBUG) без зупинки додатка для зміни конфігурації.
Розглянемо базовий GET-запит через Ktor Client. Створюється HttpClient з встановленим плагіном ContentNegotiation для JSON. Запит виконується через suspend-функцію get(), результат автоматично десеріалізується в data class.
data class User(
val login: String,
val id: Int,
val avatarUrl: String
)
val client = HttpClient {
install(ContentNegotiation) {
json(Json {
ignoreUnknownKeys = true
})
}
}
suspend fun getUser(): User {
return client.get("https://api.github.com/users/octocat").body()
}
Для POST-запиту з тілом використовується функція post() з contentType() та body(). Ktor автоматично серіалізує об'єкт в JSON через встановлений ContentNegotiation. DSL-стиль робить код послідовним та читабельним.
data class CreateRepo(
val name: String,
val description: String,
val private: Boolean
)
suspend fun createRepo(): Unit {
val repo = CreateRepo(
name = "my-project",
description = "Sample project",
private = false
)
client.post("https://api.github.com/user/repos") {
contentType(ContentType.Application.Json)
setBody(repo)
}
}
HttpTimeout та DefaultRequest — два ключових плагіни для конфігурації. HttpTimeout встановлює ліміти часу, а DefaultRequest задає заголовки та параметри URL для всіх запитів, позбавляючи від дублювання коду в кожному виклику.
val client = HttpClient {
install(HttpTimeout) {
connectTimeoutMillis = 15000
requestTimeoutMillis = 30000
}
install(DefaultRequest) {
url("https://api.github.com/")
header("Accept", "application/json")
}
}
Мультиплатформенність — головна перевага Ktor перед OkHttp та Retrofit. Ktor Client працює на JVM (Android, Server), Native (iOS, macOS, Windows, Linux) та JS (Browser). Один і той самий код HTTP-клієнта виконується на всіх платформах без змін, що особливо цінно для Kotlin Multiplatform проектів.
Для кожної платформи Ktor використовує свій двигун (engine). На Android за замовчуванням застосовується OkHttp-двигун, що дає повну сумісність з OkHttp-екосистемою. На iOS використовується DarwinEngine, заснований на URLSession. Для Server — CIOEngine (Coroutine I/O). Двигун можна вказати явно: HttpClient(OkHttp) { } або HttpClient(Darwin) { }.
При виборі двигуна враховуйте його можливості: OkHttp-двигун підтримує HTTP/2 та пул з'єднань, DarwinEngine — нативну інтеграцію з iOS-мережею та фонові сесії URLSession, CIOEngine — чисту корутинну реалізацію без зовнішніх залежностей. Для Web-таргетів використовується JsEngine або BrowserEngine, що працює через fetch API.
Завдяки єдиному API на всіх платформах, код для завантаження даних виглядає однаково на Android, iOS та Desktop. Це скорочує дублювання коду на 60–80% у KMM-проектах порівняно з роздільними реалізаціями на Retrofit (Android) та URLSession (iOS). Плагіни також працюють на всіх платформах без змін.
Ігнорування закриття HttpClient — часта помилка в Ktor. HttpClient реалізує Closeable, і його потрібно закривати при завершенні роботи додатка через client.close(). В Android це робиться в onDestroy() Activity або ViewModel.onCleared(). Незакритий клієнт призводить до витоку корутин та потоків двигуна.
Неправильний порядок плагінів може зламати обробку запиту. Наприклад, ContentNegotiation повинен бути встановлений до DefaultRequest, щоб тип контенту застосовувався коректно. Logging рекомендується встановлювати останнім, щоб логувати фінальну версію запиту після всіх модифікацій. Експериментуйте з порядком, якщо плагіни поводяться неочікувано.
Відсутність обробки винятків у suspend-функціях. Ktor викидає винятки IOException при мережевих помилках та ClientRequestException при HTTP-статусах 4xx. Блок try-catch обов'язковий для кожного виклику get(), post() та інших методів. Використовуйте HttpResponseValidator у блоці HttpClient для глобальної обробки помилок без дублювання try-catch у кожному методі.
Часті запитання
Ktor використовує Kotlin DSL та плагіни без анотацій та рефлексії. Retrofit побудований на Java-анотаціях та рефлексії. Ktor підтримує мультиплатформенність, Retrofit — тільки JVM/Android. Ktor нативно працює з корутинами, Retrofit додав suspend через обгортку.
Для Android оптимальний OkHttp-двигун — він забезпечує сумісність з OkHttp-екосистемою, пул з'єднань, кешування та HTTP/2. Вибирайте його через HttpClient(OkHttp) { }. Альтернатива — CIOEngine, вбудований в Ktor, але він менш стабільний на Android.
Так, Ktor підтримує HTTP/2 через відповідний двигун. OkHttp-двигун успадковує підтримку HTTP/2 від OkHttp. DarwinEngine на iOS підтримує HTTP/2 через URLSession. CIOEngine підтримує HTTP/2 на серверній стороні. Вибір двигуна визначає рівень підтримки протоколу.
Використовуйте плагін Auth з встановленням bearer { }. Плагін автоматично додає заголовок Authorization до кожного запиту та може оновлювати токен при відповіді 401 через refreshTokens. Приклад: install(Auth) { bearer { loadTokens { BearerTokens(token, refreshToken) } } }.
Так, Ktor Client повноцінно працює на iOS через DarwinEngine, що використовує URLSession. Всі плагіни, серіалізація та корутини працюють на iOS так само, як на Android. Це робить Ktor основним HTTP-клієнтом для Kotlin Multiplatform Mobile (KMM) проектів.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також