OkHttp یک کلاینت HTTP با کارایی بالا برای Android و Kotlin است که توسط شرکت Square به عنوان پایهای برای Retrofit و سایر کتابخانههای شبکه توسعه یافته است. این کتابخانه مدیریت کارآمد اتصالات، کشگذاری داخلی و پشتیبانی از HTTP/2 را فراهم میکند. به گزارش Square, 2025، OkHttp روزانه میلیاردها درخواست را در برنامههای سراسر جهان پردازش میکند.
نکات اصلی
OkHttp یک کلاینت HTTP کارآمد برای Java، Android و Kotlin است که توسط شرکت Square توسعه یافته است. این کتابخانه API سطح پایین برای انجام درخواستهای HTTP با پشتیبانی از HTTP/2، SPDY، WebSocket و بازیابی خودکار اتصالات در هنگام خرابی شبکه ارائه میدهد.
OkHttp در سال 2013 به عنوان پاسخی به نیاز به یک کلاینت HTTP قابل اعتماد ظاهر شد که مشکلات HttpURLConnection — عدم وجود pool اتصال، پشتیبانی ضعیف از HTTP/2 و API ناخوشایند — را حل کند. تا سال 2025، OkHttp در سطح سیستم Android API استفاده میشود: OkHttp از Android 4.4 (API 19) در پیادهسازی HttpURLConnection تعبیه شده است.
بر اساس دادههای Google I/O 2024، OkHttp بیش از 70٪ از تمام درخواستهای HTTP در اکوسیستم Android را پردازش میکند. این امکان وجود دارد زیرا OkHttp لایه انتقالی برای Retrofit، Apollo GraphQL، Firebase و بسیاری از کتابخانههای دیگر است. توسعهدهندگان به طور خودکار عملکرد OkHttp را بدون اتصال صریح آن دریافت میکنند.
معماری OkHttp بر روی زنجیره رهگیر (Interceptor chain) ساخته شده است. هر درخواست از یک دنباله از رهگیرها عبور میکند که میتوانند Request، Response را تغییر دهند یا اجرا را متوقف کنند. این معماری شبیه الگوی Chain of Responsibility است و امکان گسترش انعطافپذیر عملکرد را فراهم میکند.
هنگامی که برنامه یک درخواست ارسال میکند، OkHttp مراحل زیر را انجام میدهد: DNS را حل میکند، یک اتصال از pool انتخاب میکند (یا یک اتصال جدید ایجاد میکند)، TLS handshake را باز میکند (اگر HTTPS باشد)، درخواست HTTP را ارسال میکند، پاسخ را دریافت میکند و آن را به برنامه برمیگرداند. RealCall یک کلاس داخلی است که چرخه عمر کامل درخواست را از ایجاد تا تکمیل مدیریت میکند.
OkHttp به طور خودکار تغییرمسیرها (302, 301) را مدیریت میکند، درخواستها را در هنگام خرابی شبکه تکرار میکند (retry)، از پروتکل keep-alive پیروی میکند و از فشردهسازی شفاف gzip پشتیبانی میکند. توسعهدهنده نیازی به نوشتن کد برای این عملیات ندارد — OkHttp آنها را بر اساس هدرهای سرور به طور خودکار انجام میدهد.
HTTP/2 امکان ارسال چندین درخواست را از طریق یک اتصال TCP به طور همزمان، بدون مسدود کردن (head-of-line blocking مربوط به HTTP/1.1) فراهم میکند. OkHttp اگر سرور از این پروتکل پشتیبانی کند، به طور خودکار از HTTP/2 استفاده میکند و در صورت نیاز شفاف به HTTP/1.1 تغییر میکند.
مالتیپلکسینگ HTTP/2 به ویژه برای برنامههای موبایل مهم است، جایی که تأخیر برقراری اتصال (TCP + TLS) میتواند 100–300 میلیثانیه باشد. به جای 10 اتصال متوالی، OkHttp از یک اتصال استفاده میکند و کل تأخیر را در دستگاههای معمولی Android با اتصال ناپایدار 40–60٪ کاهش میدهد.
Interceptor یک رابط با یک متد intercept(Chain) است که Request دریافت میکند، اقدامات را انجام میدهد و Response را برمیگرداند. رهگیرها دو نوع هستند: رهگیرهای برنامه (اضافه شده از طریق addInterceptor) و رهگیرهای شبکه (addNetworkInterceptor).
رهگیرهای برنامه قبل از تشکیل درخواست HTTP فعال میشوند — آنها Request اصلی و Response نهایی را پس از تمام تبدیلها میبینند. رهگیرهای شبکه در سطح شبکه فعال میشوند: آنها درخواست را پس از فشردهسازی gzip، اضافه شدن هدرهای Content-Length، تغییرمسیرها و تلاشهای مجدد میبینند. اگر پاسخ از کش دریافت شود، رهگیرهای شبکه فراخوانی نمیشوند.
| نوع رهگیر | روش افزودن | زمان فراخوانی | کش را میبیند |
|---|---|---|---|
| Application Interceptor | addInterceptor() | قبل و بعد از درخواست | بله |
| Network Interceptor | addNetworkInterceptor() | در سطح شبکه | خیر |
در عمل، رهگیرهای OkHttp سه وظیفه اصلی را حل میکنند: احراز هویت (اضافه کردن هدر Authorization)، ورود به سیستم (HttpLoggingInterceptor برای اشکالزدایی) و تلاش مجدد (تکرار خودکار درخواست در هنگام خرابی شبکه). با ترکیب چند رهگیر، میتوان یک pipeline کامل پردازش درخواست بدون تکرار کد در هر فراخوانی HTTP برنامه ساخت.
ترتیب افزودن رهگیرها مهم است: Interceptor اضافه شده اول، در ورود اول و در خروج آخر اجرا میشود. برای NetworkInterceptor ترتیب توسط پشته شبکه تعیین میشود. ترتیب توصیه شده: AuthInterceptor (توکن اضافه میکند)، LoggingInterceptor (درخواست را ثبت میکند)، RetryInterceptor (در خرابی تکرار میکند).
برای اشکالزدایی درخواستهای شبکه از HttpLoggingInterceptor — یک رهگیر آماده از Square استفاده میشود. این رهگیر متد، URL، هدرها و بدنه درخواست و پاسخ را ثبت میکند. سطوح ورود به سیستم: BASIC (متد + URL + کد)، HEADERS (با هدرها) و BODY (درخواست و پاسخ کامل). BODY در هنگام توسعه مفید است، اما در تولید به دلایل امنیتی و عملکرد غیرفعال میشود.
بیایید درخواست GET پایه را از طریق OkHttp بررسی کنیم. ابتدا OkHttpClient ایجاد میشود — یک شی سنگین که یک بار ایجاد و مجدداً استفاده میشود. سپس Request با URL تشکیل میشود و درخواست به صورت همزمان از طریق execute یا ناهمزمان از طریق enqueue اجرا میشود.
val client = OkHttpClient.Builder()
.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(15, TimeUnit.SECONDS)
.build()
val request = Request.Builder()
.url("https://api.github.com/users/octocat")
.header("Accept", "application/vnd.github.v3+json")
.build()
val response = client.newCall(request).execute()
println(response.body()?.string())
برای اجرای ناهمزمان از متد enqueue استفاده میشود که Callback دریافت میکند. OkHttp درخواست را در یک نخ پسزمینه اجرا میکند و نتیجه را در همان نخ به callback برمیگرداند. برای تغییر به نخ اصلی Android از Handler یا کروتین استفاده کنید.
client.newCall(request).enqueue(object : Callback {
override fun onFailure(
call: Call, e: IOException
) {
println("درخواست ناموفق بود: ${e.message}")
}
override fun onResponse(
call: Call, response: Response
) {
println(response.body()?.string())
}
})
یک Interceptor سفارشی یک توکن Bearer به هر درخواست اضافه میکند. رهگیر حضور هدر Authorization را بررسی میکند و اگر توکن هنوز تنظیم نشده باشد، آن را از ذخیرهگاه اضافه میکند. در پاسخ 401، رهگیر میتواند توکن را از طریق Authenticator بهروزرسانی کند.
class AuthInterceptor(
private val tokenProvider: () -> String?
) : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val originalRequest = chain.request()
val token = tokenProvider.invoke()
val request = originalRequest.newBuilder()
.header("Authorization", "Bearer $token")
.build()
return chain.proceed(request)
}
}
اتصال pool (ConnectionPool) — بهینهسازی کلیدی OkHttp است که امکان استفاده مجدد از اتصالات TCP را برای چندین درخواست فراهم میکند. به جای ایجاد سوکت جدید برای هر درخواست، OkHttp تا 5 اتصال غیرفعال (به طور پیشفرض) را به مدت 5 دقیقه ذخیره میکند که تأخیر را برای درخواستهای تکراری به همان هاست 30–70٪ کاهش میدهد.
کشگذاری پاسخها از طریق کلاس Cache پیادهسازی میشود. برای فعال کردن کش، کافی است دایرکتوری و حداکثر اندازه را در OkHttpClient.Builder مشخص کنید. OkHttp به طور خودکار پاسخهای GET را مطابق با هدرهای Cache-Control، Expires و ETag ذخیره میکند و دادههای ذخیره شده را بدون درخواست شبکه برمیگرداند، اگر منقضی نشده باشند.
val cacheDir = File(context.cacheDir, "http-cache")
val cache = Cache(cacheDir, 10L * 1024 * 1024)
val client = OkHttpClient.Builder()
.cache(cache)
.connectionPool(ConnectionPool(5, 5, TimeUnit.MINUTES))
.build()
پیکربندی صحیح pool و کش به ویژه برای برنامههایی با درخواستهای مکرر — فیدهای خبری، چتها، بهروزرسانی دادهها — مهم است. بدون pool، هر اتصال TCP نیاز به دست دادن سهطرفه (SYN, SYN-ACK, ACK) و احتمالاً دست دادن TLS (2–3 round-trip) دارد که 100–500 میلیثانیه به هر درخواست اضافه میکند.
OkHttp همچنین از WebSocket از طریق کلاس RealWebSocket پشتیبانی میکند. اتصال WebSocket از طریق دست دادن HTTP (101 Switching Protocols) برقرار میشود و سپس به پروتکل دوطرفه تغییر میکند. OkHttp به طور خودکار فریمهای ping را برای زنده نگه داشتن اتصال ارسال میکند و در صورت قطع شدن دوباره متصل میشود. WebSocket از OkHttp با نقاط پایانی استانداردی مانند wss://echo.websocket.org سازگار است.
ایجاد OkHttpClient برای هر درخواست — رایجترین اشتباه. OkHttpClient شامل pool اتصال، کش و pool نخ است. ایجاد یک نمونه جدید برای هر درخواست نه تنها حافظه را هدر میدهد، بلکه مزیت استفاده مجدد از اتصالات را نیز از بین میبرد. OkHttpClient باید از طریق کانتینر DI یک singleton باشد.
نادیده گرفتن بستن Response.body() منجر به نشت منابع میشود. ResponseBody شامل InputStream است که باید پس از خواندن بسته شود. اگر از body().string() یا body().bytes() استفاده شود، OkHttp جریان را به طور خودکار میبندد، اما هنگام خواندن body().byteStream() یا body().charStream()، فراخوانی صریح close() در بلوک finally مورد نیاز است.
عدم مدیریت Timeout — مشکل دیگر. به طور پیشفرض OkHttp تایماوت ندارد (connectTimeout = 10 ثانیه، readTimeout = 10 ثانیه، writeTimeout = 10 ثانیه). برای برنامههای موبایل با اتصال ناپایدار، توصیه میشود connectTimeout 15–30 ثانیه و readTimeout 15–30 ثانیه تنظیم شود، در غیر این صورت کاربر با سیگنال ضعیف خیلی طولانی منتظر میماند.
سوالات متداول
OkHttp یک کلاینت HTTP سطح پایین با مدیریت دستی Request و Response است. Retrofit یک لایه سطح بالا با حاشیهنویسی است. OkHttp به عنوان حملونقل برای Retrofit استفاده میشود، اما میتواند بدون کتابخانههای اضافی به طور مستقل نیز کار کند.
OkHttp از SSLSocketFactory برای دست دادن TLS استفاده میکند. این کتابخانه از CertificatePinner برای اتصال گواهی (Certificate Pinning)، TrustManager برای اعتبارسنجی سفارشی و HostnameVerifier برای بررسی نام هاست در برابر گواهی پشتیبانی میکند.
درخواستهای همزمان در صورت مشکلات شبکه IOException پرتاب میکنند. درخواستهای ناهمزمان فراخوانی onFailure را با IOException دریافت میکنند. برای خطاهای HTTP (4xx, 5xx) پاسخ موفق در نظر گرفته میشود — کد خطا از طریق response.isSuccessful() بررسی میشود.
بله، OkHttp دارای پشتیبانی داخلی از WebSocket از طریق کلاس WebSocket و WebSocketListener است. پس از برقراری اتصال، WebSocket امکان ارسال و دریافت پیامها در زمان واقعی بدون درخواستهای HTTP تکراری را فراهم میکند.
تغییرمسیرهای خودکار را از طریق followRedirects(false) و followSslRedirects(false) در OkHttpClient.Builder غیرفعال کنید. این زمانی مفید است که نیاز به پردازش دستی تغییرمسیر دارید، به عنوان مثال، برای استخراج توکن از URL تغییرمسیر.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید