Ktor là một HTTP client không đồng bộ cho Kotlin, được JetBrains phát triển như một phần của framework cùng tên dành cho phát triển máy chủ và máy khách. Ktor được xây dựng trên coroutines của Kotlin và hỗ trợ đa nền tảng. Theo JetBrains, 2025, Ktor cung cấp tích hợp gốc với hệ sinh thái Kotlin mà không cần reflection và phụ thuộc bổ sung.
Những điểm chính
Ktor là một framework để xây dựng các ứng dụng máy chủ và máy khách không đồng bộ bằng Kotlin, được tạo bởi JetBrains. Ktor Client là phần phía máy khách của framework, cung cấp một HTTP client với hỗ trợ đầy đủ cho coroutines Kotlin, đa nền tảng (JVM, Native, JS) và kiến trúc mô-đun dựa trên plugin.
Ktor xuất hiện vào năm 2018 như một giải pháp thay thế cho Retrofit và OkHttp cho các dự án Kotlin-first. Không giống như Retrofit, đã chuyển cách tiếp cận Java với chú thích, Ktor Client sử dụng Kotlin DSL để cấu hình yêu cầu — không cần chú thích và reflection. Điều này làm cho mã dễ đọc hơn và an toàn kiểu hơn cho các nhà phát triển Kotlin.
Theo khảo sát Kotlin Multiplatform 2024, Ktor Client được sử dụng trong 35% dự án Kotlin Multiplatform Mobile (KMM), trở thành HTTP client phổ biến thứ hai sau OkHttp trong cộng đồng Kotlin. Ktor được ưa chuộng trong các dự án mà hỗ trợ đa nền tảng và tích hợp gốc với hệ sinh thái Kotlin là quan trọng.
Kiến trúc Ktor Client dựa trên một pipeline các plugin. Mỗi yêu cầu đi qua một chuỗi các plugin đã cài đặt có thể sửa đổi yêu cầu, phản hồi hoặc thực hiện các hành động phụ — ghi log, nén, tuần tự hóa, xác thực.
Khi tạo một HTTP client qua khối DSL HttpClient { }, bạn chỉ định engine (OkHttp, Android, CIO, Darwin) và cài đặt các plugin. Mỗi engine triển khai việc gửi yêu cầu cấp thấp cho một nền tảng cụ thể: trên Android sử dụng engine OkHttp, trên iOS — Darwin (URLSession), trên Desktop — CIO (Coroutine I/O). HttpClient tự động chọn engine tối ưu cho nền tảng hiện tại.
Một yêu cầu trong Ktor Client được thực thi qua hàm suspend, có nghĩa là tích hợp hoàn toàn với coroutines. Không Callback, không RxJava hay LiveData — chỉ mã tuần tự với suspend hoạt động không đồng bộ mà không chặn luồng.
Pipeline Ktor bao gồm các giai đoạn: đầu tiên yêu cầu đi qua các plugin đã cài đặt (ví dụ: ContentNegotiation cho JSON, Logging cho nhật ký), sau đó engine thực thi yêu cầu HTTP, và phản hồi lại đi qua các plugin để giải tuần tự hóa. Mỗi plugin là một hàm suspend thực thi trong coroutine của pipeline.
Một lợi thế quan trọng của pipeline Ktor là khả năng thực hiện xử lý có điều kiện. Một plugin có thể kiểm tra URL hoặc tiêu đề yêu cầu và bỏ qua xử lý nếu điều kiện không được đáp ứng. Ví dụ: ContentEncoding với gzip chỉ được áp dụng cho các phản hồi có chứa tiêu đề Content-Encoding: gzip, và Auth chỉ kích hoạt cho các endpoint được bảo vệ mà không ảnh hưởng đến API công cộng.
Cách tiếp cận pipeline này cho phép bạn kết hợp các plugin một cách linh hoạt: bạn có thể cài đặt ContentNegotiation với JSON, thêm Auth với token Bearer, bật nén ContentEncoding và HttpTimeout — và tất cả sẽ hoạt động cùng nhau theo đúng thứ tự. Thứ tự cài đặt plugin rất quan trọng: plugin được cài đặt đầu tiên sẽ xử lý yêu cầu trước các plugin khác.
Plugin là hệ thống mở rộng mô-đun của Ktor, thay thế các chú thích Retrofit và bộ chặn OkHttp. Mỗi plugin giải quyết một tác vụ cụ thể và được cài đặt qua hàm install() trong khối HttpClient. Ktor cung cấp các plugin tích hợp sẵn và cũng cho phép tạo plugin tùy chỉnh.
| Plugin | Mục đích |
|---|---|
| ContentNegotiation | Tuần tự hóa và giải tuần tự hóa JSON, XML qua Kotlinx Serialization |
| Logging | Ghi log yêu cầu và phản hồi với mức cấu hình được |
| Auth | Xác thực: Basic, Bearer, Digest với làm mới token tự động |
| HttpTimeout | Cấu hình thời gian chờ kết nối, đọc và yêu cầu |
| ContentEncoding | Nén gzip và deflate trong suốt |
| DefaultRequest | Đặt giá trị mặc định cho tất cả yêu cầu |
Cho các tác vụ cụ thể, một plugin tùy chỉnh được tạo qua createClientPlugin. Plugin có thể chặn yêu cầu (onRequest), phản hồi (onResponse) hoặc xử lý lỗi (onError). Điều này hoàn toàn thay thế Interceptor của OkHttp, nhưng với API Kotlin được định kiểu và hỗ trợ hàm suspend.
Plugin tùy chỉnh thuận tiện cho việc thêm số liệu, logic thử lại tự động, theo dõi yêu cầu hoặc kiểm thử A/B các endpoint. Không giống như bộ chặn OkHttp, plugin Ktor được viết bằng Kotlin và chạy trong ngữ cảnh coroutine, đơn giản hóa việc xử lý lỗi và thời gian chờ.
Để gỡ lỗi yêu cầu, plugin Logging được sử dụng với mức ALL, HEADERS hoặc BODY. Logging xuất phương thức, URL, trạng thái, tiêu đề và nội dung của yêu cầu và phản hồi. Không giống như HttpLoggingInterceptor của OkHttp, Ktor Logging hoạt động không đồng bộ và có thể được cấu hình để lọc theo mức log (ERROR, WARN, INFO, DEBUG) mà không cần dừng ứng dụng để thay đổi cấu hình.
Hãy xem xét một yêu cầu GET cơ bản bằng Ktor Client. Một HttpClient được tạo với plugin ContentNegotiation được cài đặt cho JSON. Yêu cầu được thực thi qua hàm suspend get(), và kết quả tự động được giải tuần tự hóa thành một 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()
}
Cho yêu cầu POST có nội dung, hàm post() được sử dụng với contentType() và body(). Ktor tự động tuần tự hóa đối tượng thành JSON qua ContentNegotiation đã cài đặt. Phong cách DSL làm cho mã tuần tự và dễ đọc.
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 và DefaultRequest là hai plugin chính cho cấu hình. HttpTimeout đặt giới hạn thời gian, và DefaultRequest chỉ định tiêu đề và tham số URL cho tất cả yêu cầu, loại bỏ trùng lặp mã trong mỗi lần gọi.
val client = HttpClient {
install(HttpTimeout) {
connectTimeoutMillis = 15000
requestTimeoutMillis = 30000
}
install(DefaultRequest) {
url("https://api.github.com/")
header("Accept", "application/json")
}
}
Đa nền tảng là lợi thế chính của Ktor so với OkHttp và Retrofit. Ktor Client chạy trên JVM (Android, Server), Native (iOS, macOS, Windows, Linux) và JS (Browser). Cùng một mã HTTP client chạy trên tất cả các nền tảng mà không cần thay đổi, điều này đặc biệt có giá trị cho các dự án Kotlin Multiplatform.
Cho mỗi nền tảng, Ktor sử dụng engine riêng của nó. Trên Android, engine OkHttp được sử dụng mặc định, cung cấp khả năng tương thích hoàn toàn với hệ sinh thái OkHttp. Trên iOS, DarwinEngine được sử dụng, dựa trên URLSession. Cho Server — CIOEngine (Coroutine I/O). Engine có thể được chỉ định rõ ràng: HttpClient(OkHttp) { } hoặc HttpClient(Darwin) { }.
Khi chọn engine, hãy xem xét khả năng của nó: engine OkHttp hỗ trợ HTTP/2 và nhóm kết nối, DarwinEngine cung cấp tích hợp mạng iOS gốc và các phiên URLSession nền, CIOEngine là một triển khai coroutine thuần túy không có phụ thuộc bên ngoài. Cho các mục tiêu Web, JsEngine hoặc BrowserEngine được sử dụng, hoạt động qua fetch API.
Nhờ API thống nhất trên tất cả các nền tảng, mã để tải dữ liệu trông giống nhau trên Android, iOS và Desktop. Điều này giảm trùng lặp mã 60–80% trong các dự án KMM so với các triển khai riêng biệt trên Retrofit (Android) và URLSession (iOS). Các plugin cũng hoạt động trên tất cả các nền tảng mà không cần thay đổi.
Bỏ qua việc đóng HttpClient là một lỗi phổ biến trong Ktor. HttpClient triển khai Closeable và phải được đóng khi ứng dụng kết thúc qua client.close(). Trên Android, điều này được thực hiện trong onDestroy() của Activity hoặc ViewModel.onCleared(). Một client không được đóng dẫn đến rò rỉ coroutines và luồng engine.
Thứ tự plugin sai có thể phá vỡ xử lý yêu cầu. Ví dụ: ContentNegotiation nên được cài đặt trước DefaultRequest để loại nội dung được áp dụng chính xác. Logging được khuyến nghị cài đặt cuối cùng để ghi lại phiên bản cuối cùng của yêu cầu sau tất cả các sửa đổi. Hãy thử nghiệm thứ tự nếu các plugin hoạt động bất ngờ.
Thiếu xử lý ngoại lệ trong các hàm suspend. Ktor ném IOException cho lỗi mạng và ClientRequestException cho trạng thái HTTP 4xx. Khối try-catch là bắt buộc cho mọi lời gọi đến get(), post() và các phương thức khác. Sử dụng HttpResponseValidator trong khối HttpClient để xử lý lỗi toàn cục mà không trùng lặp try-catch trong mỗi phương thức.
Câu hỏi thường gặp
Ktor sử dụng Kotlin DSL và plugin không cần chú thích và reflection. Retrofit được xây dựng trên chú thích Java và reflection. Ktor hỗ trợ đa nền tảng, Retrofit chỉ JVM/Android. Ktor hoạt động gốc với coroutines, Retrofit thêm suspend qua một wrapper.
Cho Android, engine OkHttp là tối ưu — nó cung cấp khả năng tương thích với hệ sinh thái OkHttp, nhóm kết nối, bộ nhớ đệm và HTTP/2. Chọn nó qua HttpClient(OkHttp) { }. Thay thế là CIOEngine tích hợp trong Ktor, nhưng nó kém ổn định hơn trên Android.
Có, Ktor hỗ trợ HTTP/2 qua engine thích hợp. Engine OkHttp kế thừa hỗ trợ HTTP/2 từ OkHttp. DarwinEngine trên iOS hỗ trợ HTTP/2 qua URLSession. CIOEngine hỗ trợ HTTP/2 ở phía máy chủ. Việc chọn engine xác định mức độ hỗ trợ giao thức.
Sử dụng plugin Auth với thiết lập bearer { }. Plugin tự động thêm tiêu đề Authorization vào mỗi yêu cầu và có thể làm mới token khi phản hồi 401 qua refreshTokens. Ví dụ: install(Auth) { bearer { loadTokens { BearerTokens(token, refreshToken) } } }.
Có, Ktor Client hoạt động đầy đủ trên iOS qua DarwinEngine, sử dụng URLSession. Tất cả plugin, tuần tự hóa và coroutines hoạt động trên iOS giống như trên Android. Điều này làm cho Ktor trở thành HTTP client chính cho các dự án Kotlin Multiplatform Mobile (KMM).
Tóm tắt
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.
Đọc thêm