Ktor: چیست، ویژگی‌های کلاینت HTTP ناهمزمان

نویسنده: IT Sectr منتشر شده: 2026-03-07 زمان مطالعه: 8 دقیقه

Ktor یک کلاینت HTTP ناهمزمان برای Kotlin است که توسط شرکت JetBrains به عنوان بخشی از فریم‌ورک همنام برای توسعه سمت سرور و کلاینت ساخته شده است. Ktor بر پایه کوروتین‌های Kotlin ساخته شده و از چندسکویی پشتیبانی می‌کند. بر اساس داده‌های JetBrains, 2025، Ktor یکپارچگی بومی با اکوسیستم Kotlin را بدون بازتاب (reflection) و وابستگی‌های اضافی فراهم می‌کند.

نکات کلیدی

  • Ktor — کلاینت HTTP ناهمزمان در Kotlin با پشتیبانی چندسکویی
  • کوروتین‌ها — اساس اجرای درخواست‌ها بدون callback و جریان‌های واکنش‌گرا
  • پلاگین‌ها — سیستم توسعه‌پذیر ماژولار برای سریالایز، لاگینگ و احراز هویت
  • چندسکویی — یک کد برای Android، iOS، Desktop و Server
  • Kotlinx Serialization — سریالایز بومی بدون بازتاب از طریق @Serializable

Ktor چیست؟

Ktor یک فریم‌ورک برای ساخت برنامه‌های ناهمزمان سمت سرور و کلاینت در Kotlin است که توسط شرکت JetBrains ساخته شده است. Ktor Client — بخش کلاینت فریم‌ورک است که یک کلاینت HTTP با پشتیبانی کامل از کوروتین‌های Kotlin، چندسکویی (JVM, Native, JS) و معماری ماژولار مبتنی بر پلاگین ارائه می‌دهد.

Ktor در سال 2018 به عنوان جایگزینی برای Retrofit و OkHttp در پروژه‌های Kotlin-first ظاهر شد. بر خلاف Retrofit که رویکرد Java را با نویسه‌ها (annotation) port کرده بود، Ktor Client از Kotlin DSL برای پیکربندی درخواست‌ها استفاده می‌کند — بدون نویسه و بازتاب. این کار کد را برای توسعه‌دهندگان Kotlin خواناتر و نوع-ایمن‌تر می‌کند.

بر اساس نظرسنجی Kotlin Multiplatform 2024، Ktor Client در 35% پروژه‌های Kotlin Multiplatform Mobile (KMM) استفاده می‌شود که آن را به دومین کلاینت HTTP محبوب بعد از OkHttp در جامعه Kotlin تبدیل می‌کند. Ktor در پروژه‌هایی که چندسکویی و یکپارچگی بومی با اکوسیستم Kotlin مهم است ترجیح داده می‌شود.

Ktor Client چگونه کار می‌کند

معماری Ktor Client بر اساس خط لوله (pipeline) از پلاگین‌ها است. هر درخواست از دنباله‌ای از پلاگین‌های نصب شده عبور می‌کند که می‌توانند درخواست، پاسخ را تغییر دهند یا اقدامات جانبی انجام دهند — لاگینگ، فشرده‌سازی، سریالایز، احراز هویت.

هنگام ایجاد کلاینت HTTP از طریق بلوک HttpClient { } DSL، موتور (OkHttp, Android, CIO, Darwin) را مشخص کرده و پلاگین‌ها را نصب می‌کنید. هر موتور ارسال سطح پایین درخواست را برای یک پلتفرم خاص پیاده‌سازی می‌کند: در Android از موتور OkHttp استفاده می‌شود، در iOS — Darwin (URLSession)، در Desktop — CIO (Coroutine-based I/O). HttpClient به طور خودکار موتور بهینه را برای پلتفرم جاری انتخاب می‌کند.

درخواست در Ktor Client از طریق تابع suspend اجرا می‌شود که به معنای یکپارچگی کامل با کوروتین‌ها است. هیچ Callback، RxJava یا LiveData — فقط کد ترتیبی با suspend که بدون مسدود کردن رشته به صورت ناهمزمان کار می‌کند.

خط لوله پردازش درخواست

خط لوله Ktor از فازها تشکیل شده است: ابتدا درخواست از پلاگین‌های نصب شده عبور می‌کند (مثلاً ContentNegotiation برای JSON، Logging برای لاگ‌ها)، سپس موتور درخواست HTTP را اجرا می‌کند و پاسخ دوباره برای سریال‌زدایی از پلاگین‌ها عبور می‌کند. هر پلاگین یک تابع suspend است که در کوروتین خط لوله اجرا می‌شود.

مزیت مهم خط لوله Ktor امکان پردازش شرطی است. پلاگین می‌تواند URL یا هدرهای درخواست را بررسی کند و اگر شرط برآورده نشد، پردازش را رد کند. مثلاً ContentEncoding با gzip فقط به پاسخ‌هایی اعمال می‌شود که هدر Content-Encoding: gzip را دارند، و Auth فقط برای endpointهای محافظت‌شده فعال می‌شود و بر APIهای عمومی تأثیر نمی‌گذارد.

این رویکرد خط لوله امکان ترکیب انعطاف‌پذیر پلاگین‌ها را فراهم می‌کند: می‌توانید ContentNegotiation با JSON نصب کنید، Auth با توکن Bearer اضافه کنید، فشرده‌سازی ContentEncoding و HttpTimeout را فعال کنید — و همه آنها با هم به ترتیب درست کار خواهند کرد. ترتیب نصب پلاگین‌ها مهم است: اولین نصب شده درخواست را زودتر از بقیه پردازش می‌کند.

پلاگین‌های Ktor Client

پلاگین‌ها — سیستم توسعه ماژولار 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 می‌شود، اما با API تایپ‌شده Kotlin و پشتیبانی از توابع suspend.

پلاگین‌های سفارشی برای افزودن معیارها، منطق خودکار تلاش مجدد، ردیابی درخواست‌ها یا تست A/B endpointها مفید هستند. بر خلاف رهگیرهای OkHttp، پلاگین‌های Ktor به زبان Kotlin نوشته شده و در زمینه کوروتین کار می‌کنند که مدیریت خطا و مهلت‌ها را ساده‌تر می‌کند.

برای اشکال‌زدایی درخواست‌ها از پلاگین Logging با سطح ALL، HEADERS یا BODY استفاده می‌شود. Logging متد، URL، وضعیت، هدرها و بدنه درخواست و پاسخ را نشان می‌دهد. بر خلاف HttpLoggingInterceptor از OkHttp، Ktor Logging به صورت ناهمزمان کار می‌کند و می‌تواند برای فیلتر بر اساس سطح لاگ (ERROR, WARN, INFO, DEBUG) بدون توقف برنامه برای تغییر پیکربندی تنظیم شود.

نمونه کدهای Ktor Client در Kotlin

درخواست GET پایه را از طریق Ktor Client بررسی می‌کنیم. یک HttpClient با پلاگین ContentNegotiation نصب شده برای JSON ایجاد می‌شود. درخواست از طریق تابع suspend get() اجرا می‌شود، نتیجه به طور خودکار به data class سریال‌زدایی می‌شود.

kotlin
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 به طور خودکار شیء را از طریق ContentNegotiation نصب شده به JSON سریالایز می‌کند. سبک DSL کد را ترتیبی و خواناتر می‌کند.

kotlin
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 را برای همه درخواست‌ها تنظیم می‌کند و از تکرار کد در هر فراخوانی جلوگیری می‌کند.

kotlin
val client = HttpClient {
    install(HttpTimeout) {
        connectTimeoutMillis = 15000
        requestTimeoutMillis = 30000
    }
    install(DefaultRequest) {
        url("https://api.github.com/")
        header("Accept", "application/json")
    }
}

پشتیبانی چندسکویی Ktor

چندسکویی — مزیت اصلی 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 یکسان به نظر می‌رسد. این کار تکرار کد را در پروژه‌های KMM تا 60–80% در مقایسه با پیاده‌سازی‌های جداگانه در Retrofit (Android) و URLSession (iOS) کاهش می‌دهد. پلاگین‌ها نیز بدون تغییر در همه پلتفرم‌ها کار می‌کنند.

خطاهای رایج هنگام کار با Ktor

نادیده گرفتن بستن HttpClient — خطای رایج در Ktor. HttpClient اینترفیس Closeable را پیاده‌سازی می‌کند و باید پس از اتمام کار برنامه از طریق client.close() بسته شود. در Android این کار در onDestroy() Activity یا ViewModel.onCleared() انجام می‌شود. کلاینت بسته نشده منجر به نشت کوروتین‌ها و رشته‌های موتور می‌شود.

ترتیب نادرست پلاگین‌ها می‌تواند پردازش درخواست را مختل کند. مثلاً ContentNegotiation باید قبل از DefaultRequest نصب شود تا نوع محتوا به درستی اعمال شود. توصیه می‌شود Logging را آخرین نصب کنید تا نسخه نهایی درخواست پس از همه تغییرات لاگ شود. اگر پلاگین‌ها غیرمنتظره رفتار می‌کنند، با ترتیب آزمایش کنید.

عدم مدیریت استثناها در توابع suspend. Ktor در خطاهای شبکه IOException و در وضعیت‌های HTTP 4xx ClientRequestException پرتاب می‌کند. بلوک try-catch برای هر فراخوانی get()، post() و سایر متدها اجباری است. از HttpResponseValidator در بلوک HttpClient برای مدیریت سراسری خطاها بدون تکرار try-catch در هر متد استفاده کنید.

سوالات متداول

Ktor چه تفاوتی با Retrofit دارد؟

Ktor از Kotlin DSL و پلاگین‌ها بدون نویسه و بازتاب استفاده می‌کند. Retrofit بر روی نویسه‌های Java و بازتاب ساخته شده است. Ktor از چندسکویی پشتیبانی می‌کند، Retrofit — فقط JVM/Android. Ktor به صورت بومی با کوروتین‌ها کار می‌کند، Retrofit suspend را از طریق یک لایه wrapper اضافه کرده است.

کدام موتور Ktor برای Android بهتر است؟

برای Android موتور OkHttp بهینه است — سازگاری با اکوسیستم OkHttp، استخر اتصالات، کش و HTTP/2 را فراهم می‌کند. آن را از طریق HttpClient(OkHttp) { } انتخاب کنید. جایگزین — CIOEngine داخلی Ktor، اما روی Android کمتر پایدار است.

آیا Ktor از HTTP/2 پشتیبانی می‌کند؟

بله، Ktor از HTTP/2 از طریق موتور مربوطه پشتیبانی می‌کند. موتور OkHttp پشتیبانی HTTP/2 را از OkHttp به ارث می‌برد. DarwinEngine در iOS از HTTP/2 از طریق URLSession پشتیبانی می‌کند. CIOEngine از HTTP/2 در سمت سرور پشتیبانی می‌کند. انتخاب موتور سطح پشتیبانی پروتکل را تعیین می‌کند.

چگونه احراز هویت را در Ktor Client تنظیم کنیم؟

از پلاگین Auth با تنظیم bearer { } استفاده کنید. پلاگین به طور خودکار هدر Authorization را به هر درخواست اضافه می‌کند و می‌تواند توکن را در پاسخ 401 از طریق refreshTokens به‌روزرسانی کند. مثال: install(Auth) { bearer { loadTokens { BearerTokens(token, refreshToken) } } }.

آیا می‌توان از Ktor Client در iOS استفاده کرد؟

بله، Ktor Client به طور کامل در iOS از طریق DarwinEngine که از URLSession استفاده می‌کند کار می‌کند. همه پلاگین‌ها، سریالایز و کوروتین‌ها در iOS مانند Android کار می‌کنند. این Ktor را به کلاینت HTTP اصلی برای پروژه‌های Kotlin Multiplatform Mobile (KMM) تبدیل می‌کند.

خلاصه

  • Ktor — کلاینت HTTP ناهمزمان از JetBrains با پشتیبانی چندسکویی
  • Kotlin DSL جایگزین نویسه‌ها — پیکربندی از طریق بلوک‌های برنامه بدون بازتاب
  • پلاگین‌ها ContentNegotiation, Auth, Logging و HttpTimeout قابلیت‌ها را به صورت ماژولار گسترش می‌دهند
  • کوروتین‌ها — اساس اجرا: همه متدها suspend بدون callback و جریان‌های واکنش‌گرا
  • چندسکویی — یک کد برای Android، iOS، Desktop، Server و JS
  • موتورها OkHttp, Darwin, CIO Ktor را با پلتفرم خاص تطبیق می‌دهند
  • HttpResponseValidator مدیریت خطاهای HTTP را بدون تکرار try-catch متمرکز می‌کند

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید