Ktor — to asynchroniczny klient HTTP i framework serwerowy dla Kotlin, obsługujący rozwój wieloplatformowy. Biblioteka oparta jest na korutynach Kotlin i działa na JVM, iOS, Android, JS oraz Native. Według danych repozytorium Ktor na GitHub, projekt jest aktywnie rozwijany przez zespół JetBrains. Ktor oferuje modułową architekturę z systemem wtyczek do elastycznej konfiguracji połączeń HTTP.
Najważniejsze
Ktor — to framework do tworzenia klientów HTTP i serwerów w języku Kotlin, opracowany przez firmę JetBrains. W przeciwieństwie do tradycyjnych bibliotek, Ktor od samego początku został zaprojektowany do rozwoju wieloplatformowego i działa na wszystkich platformach obsługiwanych przez Kotlin.
Ktor wykorzystuje podejście pośrednich handlerów, inspirowane architekturą Kodein i Express.js. Każde żądanie przechodzi przez potok funkcji handlerów, które mogą modyfikować żądanie i odpowiedź. Zapewnia to elastyczność niedostępną w bibliotekach ze sztywną architekturą opartą na adnotacjach.
Obecna wersja Ktor 3.0 obejmuje wsparcie dla Kotlin 2.0, kompilatora K2 oraz nowego silnika CIO (Coroutine I/O) z ulepszoną wydajnością. Biblioteka jest rozpowszechniana na licencji Apache 2.0 i dostępna do użytku komercyjnego bez ograniczeń.
Część kliencka Ktor jest w pełni oparta na korutynach Kotlin, co zapewnia efektywne asynchroniczne wykonywanie zapytań bez blokowania wątków. Część serwerowa umożliwia tworzenie serwerów HTTP z routingiem, obsługą żądań i połączeniami WebSocket.
Ktor wykorzystuje wtyczkową architekturę: wszystkie dodatkowe funkcje — logowanie, serializacja, uwierzytelnianie — są podłączane przez wtyczki. To czyni bibliotekę modułową i pozwala podłączać tylko niezbędne komponenty, zmniejszając rozmiar końcowej aplikacji.
Dzięki jednolitemu API na wszystkich platformach programista nie musi uczyć się różnych klientów HTTP dla iOS i Android. W projekcie wieloplatformowym kod warstwy sieciowej jest w pełni wspólny, a implementacja specyficzna dla platformy jest ukryta za silnikiem HttpClient. Skraca to czas rozwoju i zmniejsza liczbę błędów związanych z różnicami między platformami.
Ktor oferuje zestaw funkcji, które czynią go atrakcyjnym wyborem dla nowoczesnych projektów Kotlin, szczególnie wieloplatformowych.
Ktor działa na JVM, Android, iOS, macOS, Windows, Linux, JavaScript i Wasm. Ten sam kod klienta HTTP działa na wszystkich platformach bez zmian. To kluczowa zaleta w porównaniu z bibliotekami związanymi z OkHttp lub URLSession.
Korutyny Kotlin zapewniają naturalną asynchroniczność bez wywołań zwrotnych. Każde żądanie to funkcja suspend, którą można wywołać z dowolnej korutyny. Ktor obsługuje strumieniowanie odpowiedzi przez Flow, co jest wygodne dla długich połączeń i WebSocket.
Wtyczki Ktor są podłączane przez blok install i konfigurowane osobno. Główne wtyczki: ContentNegotiation do serializacji, Logging do logowania, Auth do uwierzytelniania i WebSockets do komunikacji dwukierunkowej. Każdą wtyczkę można włączyć lub wyłączyć niezależnie.
Obsługa błędów w Ktor jest oparta na wyjątkach. Klasa ClientRequestException jest zgłaszana przy kodach 4xx, ServerResponseException przy 5xx, a IOException przy błędach sieciowych. Limity czasu są konfigurowane przez wtyczkę HttpTimeout, która określa czas oczekiwania na połączenie, odczyt i zapis. Do ponownych prób używana jest wtyczka Retry z ustawieniami liczby prób i opóźnienia.
Ktor wykorzystuje architekturę potokową, gdzie każde żądanie przechodzi przez łańcuch handlerów. Klient tworzy konfigurację HttpClient z zainstalowanymi wtyczkami, a każde wywołanie metody get lub post przechodzi przez wtyczki w kolejności ich podłączenia.
Obiekt HttpClient jest tworzony z silnikiem specyficznym dla platformy: CIO dla JVM i Android, Darwin dla iOS i macOS, OkHttp dla zgodności z Android, Js dla przeglądarki. Silnik można wybrać jawnie lub pozostawić automatyczny wybór. Każde żądanie zwraca HttpResponse, który zawiera treść odpowiedzi, nagłówki i status.
val client = HttpClient(CIO) {
install(ContentNegotiation) {
json(Json {
ignoreUnknownKeys = true
})
}
}
suspend fun fetchUsers(): List<User> {
return client.get("https://api.example.com/users").body()
}
Instalacja Ktor odbywa się przez Gradle lub Maven. W projektach wieloplatformowych zależności są określane w sourceSets dla każdego targetu. Ktor jest dystrybuowany przez Maven Central.
W build.gradle.kts dodaj zależność ktor-client-core dla wspólnego kodu i silnik dla konkretnej platformy. Wersja Ktor jest ustawiana przez zmienną w gradle.properties. Ktor 3.x wymaga Kotlin 2.0+ i obsługuje kompilator K2.
val ktorVersion = "3.0.3"
dependencies {
implementation("io.ktor:ktor-client-core:$ktorVersion")
implementation("io.ktor:ktor-client-cio:$ktorVersion")
implementation("io.ktor:ktor-client-content-negotiation:$ktorVersion")
implementation("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion")
implementation("io.ktor:ktor-client-logging:$ktorVersion")
}
Dla iOS używany jest silnik Darwin, który opakowuje natywny URLSession. W Kotlin Multiplatform pozwala to uzyskać maksymalną wydajność i integrację z systemowymi mechanizmami buforowania iOS. Silnik jest dodawany jako osobna zależność w iOS sourceSet.
Ważna cecha Ktor — obsługa różnych formatów serializacji przez ContentNegotiation. Oprócz JSON, wtyczka obsługuje Protobuf, CBOR, XML i niestandardowe formaty. Do serializacji używane są biblioteki kotlinx.serialization lub Jackson, a programista może przełączać się między nimi bez zmiany kodu zapytań.
Przykłady poniżej przedstawiają typowe scenariusze pracy z klientem Ktor: podstawowe żądanie GET, wysyłanie danych i praca z kodem wieloplatformowym.
Proste żądanie GET z automatyczną deserializacją odpowiedzi do klasy danych. Ktor używa wtyczki ContentNegotiation z kotlinx.serialization do konwersji JSON na obiekty. Kod jest zwięzły i bezpieczny typowo.
@Serializable
data class Post(
val id: Int,
val title: String,
val body: String
)
suspend fun getPosts(): List<Post> {
val response = client.get("https://jsonplaceholder.typicode.com/posts")
return response.body()
}
Żądanie POST w Ktor wysyła klasę danych jako ciało JSON przez metodę post z contentType i setBody. Wtyczka ContentNegotiation automatycznie serializuje obiekt do łańcucha JSON. Odpowiedź można przetworzyć synchronicznie lub asynchronicznie.
suspend fun createPost(): Post {
val newPost = Post(
id = 0,
title = "Nowy post",
body = "Treść posta"
)
val response = client.post("https://jsonplaceholder.typicode.com/posts") {
contentType(ContentType.Application.Json)
setBody(newPost)
}
return response.body()
}
Metoda submitFormWithBinaryData w Ktor pozwala wysyłać pliki i formularze w formacie multipart. Ktor automatycznie dzieli dane na części i dodaje nagłówki. Do śledzenia postępu używany jest onUpload, który otrzymuje bajty przesłanych danych.
suspend fun uploadFile(fileBytes: ByteArray) {
client.submitFormWithBinaryData(
url = "https://api.example.com/upload",
formData = formData {
append("file", fileBytes, Headers.build {
append(HttpHeaders.ContentType, "image/png")
append(HttpHeaders.ContentDisposition, "filename=\"photo.png\"")
})
}
)
}
Wybór między Ktor a Retrofit zależy od architektury projektu i wymagań dotyczących wieloplatformowości. Retrofit pozostaje standardem dla projektów tylko na Androida, podczas gdy Ktor jest lepszym wyborem dla Kotlin Multiplatform.
Ktor oferuje również wbudowane wsparcie dla WebSocket i SSE (Server-Sent Events), co czyni go wygodnym dla aplikacji czasu rzeczywistego. Retrofit nie obsługuje WebSocket bezpośrednio — wymaga to osobnej biblioteki OkHttp WebSocket. Ktor jest również łatwiejszy w konfiguracji dla różnych środowisk dzięki systemowi wtyczek, gdzie każda wtyczka odpowiada za jedną funkcję.
Wtyczka Auth w Ktor obsługuje podstawowe uwierzytelnianie, tokeny Bearer, Digest i OAuth2. Konfiguracja uwierzytelniania odbywa się deklaratywnie: programista określa dostawcę, źródło tokena i zakres działania. Ktor automatycznie dodaje nagłówki uwierzytelniania do żądań i może odświeżać token po jego wygaśnięciu.
Jeśli projekt używa Kotlin Multiplatform ze wspólnym kodem na iOS i Android, Ktor jest jedynym rozwiązaniem, które działa na obu platformach bez dodatkowych warstw pośrednich. Retrofit jest ściśle związany z OkHttp i JVM, co czyni go nieprzydatnym dla iOS.
Dla projektów tylko na Androida Retrofit zapewnia bardziej dojrzałe API, większą liczbę konwerterów i przechwytywaczy OkHttp. Ktor w tym scenariuszu również działa, ale jego ekosystem wtyczek jest mniej rozbudowany. Obie biblioteki obsługują korutyny i zapewniają porównywalną wydajność.
| Kryterium | Ktor | Retrofit |
|---|---|---|
| Wieloplatformowość | iOS, Android, JVM, JS, Native | Tylko JVM i Android |
| Silnik HTTP | CIO, Darwin, OkHttp, Js | OkHttp |
| Konwertery | kotlinx.serialization, Jackson | Gson, Moshi, Jackson, Protobuf |
| Architektura | Potok z wtyczkami | Adnotacje z generowaniem kodu |
| Twórca | JetBrains | Square |
Często zadawane pytania
Ktor — wieloplatformowy klient HTTP na korutynach od JetBrains. Retrofit — biblioteka Android od Square oparta na OkHttp. Ktor działa na iOS, Android, JS i Native, a Retrofit — tylko na JVM.
Tak, Ktor obsługuje iOS przez silnik Darwin, który wykorzystuje natywny URLSession. Zapewnia to maksymalną wydajność i prawidłową pracę z systemowym cache iOS. Kod klienta pozostaje wspólny między platformami.
Ktor obsługuje silniki: CIO (JVM/Android), Darwin (iOS/macOS), OkHttp (Android), Js (przeglądarka), Jetty, Netty, Tomcat (serwerowe). Silnik można wybrać jawnie lub pozostawić automatyczny wybór domyślny.
Tak, Ktor ma wbudowane wsparcie dla WebSocket zarówno po stronie klienta, jak i serwera. Dla klienta używana jest wtyczka WebSockets, która pozwala ustanowić połączenie dwukierunkowe i wymieniać wiadomości w czasie rzeczywistym.
Błędy są obsługiwane przez try-catch wokół wywołań suspend. Ktor zgłasza wyjątki ClientRequestException dla 4xx, ServerResponseException dla 5xx i IOException dla błędów sieciowych. Zaleca się używanie typu Result do ujednolicenia.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również