OkHttp — какво е, възможности и архитектура на HTTP клиента

Автор: IT Sectr Публикувано: 2026-03-07 Време за четене: 8 мин

OkHttp е високопроизводителен HTTP клиент за Android и Kotlin, разработен от компанията Square като основа за Retrofit и други мрежови библиотеки. Той осигурява ефективно управление на връзките, вградено кеширане и поддръжка на HTTP/2. По данни на Square, 2025, OkHttp обработва милиарди заявки дневно в приложения по целия свят.

Основни моменти

  • OkHttp — HTTP клиент за Android и Kotlin от Square с поддръжка на HTTP/2 и SPDY
  • Пул от връзки — механизъм за повторно използване на TCP връзки за намаляване на забавянията
  • Прихващачи Interceptor и NetworkInterceptor модифицират заявки и отговори
  • Кеширане — вграден Cache намалява трафика при повторни заявки
  • WebSocket — поддръжка за двупосочна комуникация чрез протокол WebSocket

Какво е OkHttp?

OkHttp е ефективен HTTP клиент за Java, Android и Kotlin, разработен от Square. Библиотеката предоставя нискониво API за изпълнение на HTTP заявки с поддръжка на HTTP/2, SPDY, WebSocket и автоматично възстановяване на връзките при мрежови повреди.

OkHttp се появи през 2013 г. като отговор на нуждата от надежден HTTP клиент, който да реши проблемите на HttpURLConnection — липса на пул от връзки, слаба поддръжка на HTTP/2 и неудобно API. До 2025 г. OkHttp се използва на системно ниво в Android API: OkHttp е вграден в имплементацията на HttpURLConnection от Android 4.4 (API 19).

Според данни от Google I/O 2024, OkHttp обработва над 70% от всички HTTP заявки в екосистемата на Android. Това е възможно, защото OkHttp е транспортният слой за Retrofit, Apollo GraphQL, Firebase и много други библиотеки. Разработчиците получават функционалността на OkHttp автоматично, без изрично да го свързват.

Как работи OkHttp

Архитектурата на OkHttp е изградена върху верига от прихващачи (Interceptor chain). Всяка заявка преминава през последователност от прихващачи, които могат да модифицират Request, Response или да прекъснат изпълнението. Тази архитектура напомня на шаблона Chain of Responsibility и позволява гъвкаво разширяване на функционалността.

Когато приложението изпраща заявка, OkHttp изпълнява следните стъпки: разрешава DNS, избира връзка от пула (или създава нова), отваря TLS ръкостискане (ако е HTTPS), изпраща HTTP заявка, получава отговор и го връща на приложението. RealCall е вътрешен клас, който управлява пълния жизнен цикъл на заявката от създаване до завършване.

OkHttp автоматично обработва пренасочвания (302, 301), повтаря заявки при мрежови повреди (retry), следва протокола keep-alive и поддържа прозрачна gzip компресия. Разработчикът не трябва да пише код за тези операции — OkHttp ги извършва автоматично въз основа на хедърите на сървъра.

Поддръжка на HTTP/2 и мултиплексиране

HTTP/2 позволява изпращане на множество заявки чрез една TCP връзка едновременно, без блокиране (head-of-line blocking, характерен за HTTP/1.1). OkHttp автоматично използва HTTP/2, ако сървърът поддържа този протокол, и прозрачно превключва към HTTP/1.1 при необходимост.

Мултиплексирането на HTTP/2 е особено важно за мобилни приложения, където забавянето при установяване на връзка (TCP + TLS) може да бъде 100–300 ms. Вместо 10 последователни връзки, OkHttp използва една, намалявайки общото забавяне с 40–60% на типични Android устройства с нестабилна връзка.

Прихващачи на OkHttp: Interceptor и NetworkInterceptor

Interceptor е интерфейс с единствен метод intercept(Chain), който получава Request, изпълнява действия и връща Response. Прихващачите са два типа: приложни прихващачи (добавят се чрез addInterceptor) и мрежови прихващачи (addNetworkInterceptor).

Приложните прихващачи се активират преди формиране на HTTP заявката — те виждат оригиналния Request и крайния Response след всички трансформации. Мрежовите прихващачи се активират на мрежово ниво: те виждат заявката след gzip компресия, добавяне на Content-Length хедъри, пренасочвания и повторни опити. Мрежовите прихващачи не се извикват, ако отговорът е получен от кеша.

Тип прихващачМетод на добавянеКога се извикваВижда кеш
Application InterceptoraddInterceptor()Преди и след заявкаДа
Network InterceptoraddNetworkInterceptor()На мрежово нивоНе

Приложение на прихващачите на практика

На практика прихващачите на OkHttp решават три основни задачи: оторизация (добавяне на Authorization хедър), логване (HttpLoggingInterceptor за отстраняване на грешки) и повторен опит (автоматично повтаряне на заявка при мрежови повреди). Комбинирайки няколко прихващача, може да се изгради пълен pipeline за обработка на заявки без дублиране на код във всяко HTTP извикване на приложението.

Редът на добавяне на прихващачите има значение: Interceptor, добавен първи, се изпълнява първи на входа и последен на изхода. За NetworkInterceptor редът се определя от мрежовия стек. Препоръчителен ред: AuthInterceptor (добавя токен), LoggingInterceptor (логва заявката), RetryInterceptor (повтаря при повреди).

Логване чрез HttpLoggingInterceptor

За отстраняване на грешки в мрежови заявки се използва HttpLoggingInterceptor — готов прихващач от Square. Той логва метода, URL, хедърите и тялото на заявката и отговора. Нива на логване: BASIC (метод + URL + код), HEADERS (с хедъри) и BODY (пълна заявка и отговор). BODY е полезен по време на разработка, но в продукция се изключва от съображения за сигурност и производителност.

Примери за код на OkHttp в Kotlin

Нека разгледаме основна GET заявка чрез OkHttp. Първо се създава OkHttpClient — тежък обект, който се създава веднъж и се използва повторно. След това се формира Request с URL и заявката се изпълнява синхронно чрез execute или асинхронно чрез enqueue.

kotlin
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 или корутини.

kotlin
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.

kotlin
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)
    }
}

Пул от връзки и кеширане на OkHttp

Пулът от връзки (ConnectionPool) — ключова оптимизация на OkHttp, която позволява повторно използване на TCP връзки за множество заявки. Вместо да създава нов сокет за всяка заявка, OkHttp съхранява до 5 неактивни връзки (по подразбиране) за 5 минути, което намалява забавянето с 30–70% за повторни заявки към същия хост.

Кеширането на отговори се реализира чрез класа Cache. За включване на кеша е достатъчно да посочите директория и максимален размер в OkHttpClient.Builder. OkHttp автоматично кешира GET отговори според Cache-Control, Expires и ETag хедърите, връщайки кеширани данни без мрежова заявка, ако не са изтекли.

kotlin
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()

Правилното конфигуриране на пула и кеша е особено важно за приложения с чести заявки — новинарски емисии, чатове, актуализации на данни. Без пул всяка TCP връзка изисква трипосочно ръкостискане (SYN, SYN-ACK, ACK) и потенциално TLS ръкостискане (2–3 round-trip), което добавя 100–500 ms към всяка заявка.

OkHttp също поддържа WebSocket чрез класа RealWebSocket. WebSocket връзката се установява чрез HTTP ръкостискане (101 Switching Protocols) и след това превключва към двупосочен протокол. OkHttp автоматично изпраща ping рамки за поддържане на връзката жива и се пресвързва при прекъсване. WebSocket от OkHttp е съвместим със стандартни крайни точки като wss://echo.websocket.org.

Типични грешки при работа с OkHttp

Създаване на OkHttpClient за всяка заявка — най-честата грешка. OkHttpClient съдържа пула от връзки, кеша и пула от нишки. Създаването на нов екземпляр за всяка заявка не само губи памет, но и лишава от предимството на повторното използване на връзки. OkHttpClient трябва да бъде сингълтън чрез DI контейнер.

Пренебрегване на затварянето на 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 се различава от Retrofit?

OkHttp е нискониво HTTP клиент с ръчно управление на Request и Response. Retrofit е високониво обвивка с анотации. OkHttp се използва като транспорт за Retrofit, но може да работи самостоятелно без допълнителни библиотеки.

Как OkHttp обработва HTTPS?

OkHttp използва SSLSocketFactory за TLS ръкостискане. Библиотеката поддържа CertificatePinner за закрепване на сертификати (Certificate Pinning), TrustManager за персонализирано валидиране и HostnameVerifier за проверка на името на хоста спрямо сертификата.

Как да уловим мрежови грешки в OkHttp?

Синхронните заявки хвърлят IOException при мрежови проблеми. Асинхронните заявки получават извикване onFailure с IOException. За HTTP грешки (4xx, 5xx) отговорът се счита за успешен — кодът на грешката се проверява чрез response.isSuccessful().

Поддържа ли OkHttp WebSocket?

Да, OkHttp има вградена поддръжка за WebSocket чрез класовете WebSocket и WebSocketListener. След установяване на връзка, WebSocket позволява изпращане и получаване на съобщения в реално време без повторни HTTP заявки.

Как да изключим пренасочванията в OkHttp?

Изключете автоматичните пренасочвания чрез followRedirects(false) и followSslRedirects(false) в OkHttpClient.Builder. Това е полезно, когато трябва ръчно да обработите пренасочване, например за извличане на токен от URL за пренасочване.

Резюме

  • OkHttp — високопроизводителен HTTP клиент от Square с поддръжка на HTTP/2 и SPDY
  • Архитектура на прихващачите реализира Chain of Responsibility за модифициране на заявки
  • Пул от връзки използва повторно TCP връзки, намалявайки забавянето с 30–70%
  • Кеширане Cache-Control и ETag намаляват трафика при повторни заявки
  • WebSocket осигурява двупосочна комуникация в реално време
  • OkHttpClient трябва да бъде сингълтън — създаването за всяка заявка води до изтичания
  • ResponseBody изисква изрично затваряне при поточно четене на byteStream

Ще разработим мобилно приложение под ключ

IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.

Обсъдете проекта

Прочетете също