Ktor је асинхрони HTTP клијент за Kоtlin, развијен од стране компаније JetBrains као део истоименог оквира за серверски и клијентски развој. Ktor је изграђен на корутинама Kоtlin-а и подржава вишеплатформност. Према подацима JetBrains, 2025, Ktor обезбеђује изворну интеграцију са Kоtlin екосистемом без рефлексије и додатних зависности.
Главно
Ktor је оквир за изградњу асинхроних серверских и клијентских апликација у Kоtlin-у, створен од стране компаније JetBrains. Ktor Client — клијентски део оквира, који пружа HTTP клијент са пуном подршком за корутине Kоtlin-а, вишеплатформност (JVM, Native, JS) и модуларну архитектуру засновану на plugin-има.
Ktor се појавио 2018. године као алтернатива Retrofit-у и OkHttp-у за пројекте усмерене на Kоtlin. За разлику од Retrofit-а, који је пренео Java приступ са анотацијама, Ktor Client користи Kotlin DSL за конфигурацију захтева — без анотација и рефлексије. То чини код читљивијим и типно-безбеднијим за Kоtlin програмере.
Према анкети Kotlin Multiplatform 2024, Ktor Client се користи у 35% пројеката Kotlin Multiplatform Mobile (KMM), што га чини другим најпопуларнијим HTTP клијентом после OkHttp-а у Kоtlin заједници. Ktor се преферира у пројектима где су важни вишеплатформност и изворна интеграција са Kоtlin екосистемом.
Архитектура Ktor Client-а заснована је на цевоводу (pipeline) од plugin-а. Сваки захтев пролази кроз низ инсталираних plugin-а, који могу модификовати захтев, одговор или обављати споредне радње — евидентирање, компресију, серијализацију, аутентификацију.
Приликом креирања HTTP клијента кроз HttpClient { } DSL блок, наводите мотор (OkHttp, Android, CIO, Darwin) и инсталирате plugin-е. Сваки мотор имплементира слање захтева на ниском нивоу за одређену платформу: на Android-у се користи OkHttp мотор, на iOS-у — Darwin (URLSession), на Desktop-у — CIO (Coroutine-based I/O). HttpClient аутоматски бира оптимални мотор за тренутну платформу.
Захтев у Ktor Client-у се извршава преко suspend функције, што значи потпуну интеграцију са корутинама. Без Callback-а, RxJava или LiveData — само секвенцијални код са suspend који ради асинхроно без блокирања нити.
Ktor цевовод се састоји од фаза: прво захтев пролази кроз инсталиране plugin-е (нпр. ContentNegotiation за JSON, Logging за евиденцију), затим мотор извршава HTTP захтев, и одговор поново пролази кроз plugin-е за десеријализацију. Сваки plugin је suspend функција која се извршава у корутини цевовода.
Важна предност Ktor цевовода је могућност условне обраде. Plugin може проверити URL или заглавља захтева и прескочити обраду ако услов није испуњен. На пример, ContentEncoding са gzip се примењује само на одговоре који садрже заглавље Content-Encoding: gzip, а Auth се активира само за заштићене крајње тачке, не утичући на јавне API-је.
Овакав приступ цевовода омогућава флексибилно комбиновање plugin-а: можете инсталирати ContentNegotiation са JSON, додати Auth са Bearer токеном, укључити компресију ContentEncoding и HttpTimeout — и сви ће радити заједно у правилном редоследу. Редослед инсталације plugin-а је важан: први инсталирани ће обрадити захтев пре осталих.
Plugin-и — модуларни систем проширења Ktor-а, који замењује анотације Retrofit-а и пресретаче OkHttp-а. Сваки plugin решава одређени задатак и инсталира се преко функције install() у HttpClient блоку. Ktor пружа уграђене plugin-е, а такође омогућава креирање прилагођених.
| Plugin | Намена |
|---|---|
| ContentNegotiation | Серијализација и десеријализација JSON, XML преко Kotlinx Serialization |
| Logging | Евидентирање захтева и одговора са подешавањем нивоа |
| Auth | Аутентификација: Basic, Bearer, Digest са аутоматским обнављањем токена |
| HttpTimeout | Подешавање временских ограничења за повезивање, читање и захтев |
| ContentEncoding | Транспарентна gzip и deflate компресија |
| DefaultRequest | Постављање подразумеваних вредности за све захтеве |
За специфичне задатке креира се прилагођени plugin кроз createClientPlugin. Plugin може пресретати захтев (onRequest), одговор (onResponse) или обрађивати грешке (onError). Ово у потпуности замењује Interceptor из OkHttp-а, али са типизованим Kоtlin API-јем и подршком за suspend функције.
Прилагођени plugin-и су погодни за додавање метрика, аутоматске логике понављања, праћења захтева или A/B тестирања крајњих тачака. За разлику од пресретача OkHttp-а, Ktor plugin-и су написани у Kоtlin-у и раде у контексту корутине, што поједностављује обраду грешака и временских ограничења.
За отклањање грешака у захтевима користи се plugin Logging са нивоом ALL, HEADERS или BODY. Logging приказује методу, URL, статус, заглавља и тело захтева и одговора. За разлику од HttpLoggingInterceptor-а из OkHttp-а, Ktor Logging ради асинхроно и може се подесити за филтрирање по нивоу евиденције (ERROR, WARN, INFO, DEBUG) без заустављања апликације ради промене конфигурације.
Размотримо основни GET захтев кроз Ktor Client. Креира се HttpClient са инсталираним plugin-ом 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 — два кључна plugin-а за конфигурацију. 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). Plugin-и такође раде на свим платформама без измена.
Игнорисање затварања HttpClient-а — честа грешка у Ktor-у. HttpClient имплементира Closeable и мора се затворити по завршетку рада апликације преко client.close(). На Android-у се то ради у onDestroy() Activity или ViewModel.onCleared(). Незатворени клијент доводи до цурења корутина и нити мотора.
Неправилан редослед plugin-а може покварити обраду захтева. На пример, ContentNegotiation мора бити инсталиран пре DefaultRequest-а како би тип садржаја био правилно примењен. Logging се препоручује инсталирати последњим како би се евидентирала коначна верзија захтева након свих измена. Експериментишите са редоследом ако се plugin-и понашају неочекивано.
Недостатак обраде изузетака у suspend функцијама. Ktor баца изузетке IOException при мрежним грешкама и ClientRequestException при HTTP статусима 4xx. try-catch блок је обавезан за сваки позив get(), post() и других метода. Користите HttpResponseValidator у HttpClient блоку за глобалну обраду грешака без дуплирања try-catch у свакој методи.
Често постављана питања
Ktor користи Kotlin DSL и plugin-е без анотација и рефлексије. 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 на серверској страни. Избор мотора одређује ниво подршке протокола.
Користите plugin Auth са bearer { }. Plugin аутоматски додаје заглавље Authorization сваком захтеву и може обновити токен при одговору 401 преко refreshTokens. Пример: install(Auth) { bearer { loadTokens { BearerTokens(token, refreshToken) } } }.
Да, Ktor Client у потпуности ради на iOS-у преко DarwinEngine, који користи URLSession. Сви plugin-и, серијализација и корутине раде на iOS-у исто као на Android-у. То чини Ktor главним HTTP клијентом за Kotlin Multiplatform Mobile (KMM) пројекте.
Закључак
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође