Ktor هو عميل HTTP غير متزامن لـ Kotlin، طورته شركة JetBrains كجزء من الإطار الذي يحمل نفس الاسم لتطوير الخادم والعميل. تم بناء Ktor على coroutines الخاصة بـ Kotlin ويدعم التعددية المنصات. وفقًا لـ JetBrains، 2025، يوفر Ktor تكاملًا أصليًا مع نظام Kotlin البيئي دون انعكاس أو تبعيات إضافية.
النقاط الرئيسية
Ktor هو إطار لبناء تطبيقات خادم وعميل غير متزامنة بلغة Kotlin، من إنشاء JetBrains. Ktor Client هو الجزء العميلي من الإطار، ويوفر عميل HTTP مع دعم كامل لـ coroutines في Kotlin، والتعددية المنصات (JVM، Native، JS) وهندسة معيارية قائمة على الإضافات.
ظهر Ktor في 2018 كبديل لـ Retrofit وOkHttp للمشاريع التي تركز على Kotlin. على عكس Retrofit الذي نقل نهج Java مع الشروح، يستخدم Ktor Client Kotlin DSL لتكوين الطلبات — دون شروح أو انعكاس. وهذا يجعل الكود أكثر قابلية للقراءة وأمانًا من حيث الأنواع لمطوري Kotlin.
وفقًا لاستطلاع Kotlin Multiplatform 2024، يُستخدم Ktor Client في 35% من مشاريع Kotlin Multiplatform Mobile (KMM)، مما يجعله ثاني أكثر عميل HTTP شيوعًا بعد OkHttp في مجتمع Kotlin. يُفضل Ktor في المشاريع التي تكون فيها التعددية المنصات والتكامل الأصلي مع نظام Kotlin البيئي مهمين.
هندسة Ktor Client تعتمد على خط أنابيب من الإضافات. يمر كل طلب عبر سلسلة من الإضافات المثبتة التي يمكنها تعديل الطلب أو الاستجابة أو تنفيذ إجراءات جانبية — التسجيل والضغط والتسلسل والمصادقة.
عند إنشاء عميل HTTP عبر كتلة DSL HttpClient { }، تحدد المحرك (OkHttp، Android، CIO، Darwin) وتثبت الإضافات. ينفذ كل محرك إرسال الطلبات على مستوى منخفض لمنصة معينة: على Android يُستخدم محرك OkHttp، على iOS — Darwin (URLSession)، على Desktop — CIO (Coroutine I/O). HttpClient يختار تلقائيًا المحرك الأمثل للمنصة الحالية.
يتم تنفيذ الطلب في Ktor Client عبر دالة suspend، مما يعني تكاملًا كاملًا مع coroutines. لا استدعاءات، لا RxJava أو LiveData — فقط كود تسلسلي مع suspend يعمل بشكل غير متزامن دون حظر الخيط.
خط أنابيب Ktor يتكون من مراحل: أولاً يمر الطلب عبر الإضافات المثبتة (مثل ContentNegotiation لـ JSON، Logging للسجلات)، ثم ينفذ المحرك طلب HTTP، ويعود الاستجابة مرة أخرى عبر الإضافات لإلغاء التسلسل. كل إضافة هي دالة suspend تُنفذ في coroutine خط الأنابيب.
ميزة مهمة لخط أنابيب Ktor هي القدرة على المعالجة الشرطية. يمكن للإضافة التحقق من URL أو رؤوس الطلب وتخطي المعالجة إذا لم يتم استيفاء الشرط. على سبيل المثال، ContentEncoding مع gzip يُطبق فقط على الاستجابات التي تحتوي على رأس Content-Encoding: gzip، وAuth يعمل فقط للنقاط النهائية المحمية دون التأثير على واجهات API العامة.
يتيح نهج خط الأنابيب هذا دمج الإضافات بمرونة: يمكنك تثبيت 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 مطبعة ودعم دوال suspend.
الإضافات المخصصة مفيدة لإضافة المقاييس ومنطق إعادة المحاولة التلقائي وتتبع الطلبات أو اختبار A/B للنقاط النهائية. على عكس معترضات OkHttp، فإن إضافات Ktor مكتوبة بلغة Kotlin وتعمل في سياق coroutine، مما يبسط معالجة الأخطاء والمهلات.
لتصحيح أخطاء الطلبات، يُستخدم إضافة 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 محركه الخاص. على Android، يُستخدم محرك OkHttp افتراضيًا، مما يوفر توافقًا كاملاً مع نظام OkHttp البيئي. على iOS، يُستخدم DarwinEngine، القائم على URLSession. للخادم — CIOEngine (Coroutine I/O). يمكن تحديد المحرك صراحة: HttpClient(OkHttp) { } أو HttpClient(Darwin) { }.
عند اختيار محرك، ضع في اعتبارك إمكانياته: محرك OkHttp يدعم HTTP/2 وتجميع الاتصالات، DarwinEngine يوفر تكامل شبكات iOS أصلي وجلسات URLSession خلفية، CIOEngine هو تنفيذ coroutine نقي بدون تبعيات خارجية. للأهداف على الويب، يُستخدم JsEngine أو BrowserEngine، اللذان يعملان عبر fetch API.
بفضل واجهة برمجة موحدة عبر جميع المنصات، يبدو كود تحميل البيانات نفسه على Android وiOS وDesktop. وهذا يقلل تكرار الكود بنسبة 60–80% في مشاريع KMM مقارنة بالتطبيقات المنفصلة على Retrofit (Android) وURLSession (iOS). تعمل الإضافات أيضًا على جميع المنصات دون تغييرات.
تجاهل إغلاق HttpClient هو خطأ شائع في Ktor. HttpClient يطبق Closeable، ويجب إغلاقه عند انتهاء التطبيق عبر client.close(). في Android، يتم ذلك في onDestroy() لـ Activity أو ViewModel.onCleared(). العميل غير المغلق يؤدي إلى تسرب coroutines وخيوط المحرك.
ترتيب الإضافات غير الصحيح يمكن أن يعطل معالجة الطلب. على سبيل المثال، يجب تثبيت 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 يعمل أصليًا مع coroutines، 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. جميع الإضافات والتسلسل و coroutines تعمل على iOS كما تعمل على Android. وهذا يجعل Ktor عميل HTTP الرئيسي لمشاريع Kotlin Multiplatform Mobile (KMM).
الخلاصة
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.