OkHttp — co to jest, możliwości i architektura klienta HTTP

Autor: IT Sectr Opublikowano: 2026-03-07 Czas czytania: 8 min

OkHttp to wysokowydajny klient HTTP dla Android i Kotlin, opracowany przez firmę Square jako podstawa dla Retrofit i innych bibliotek sieciowych. Zapewnia efektywne zarządzanie połączeniami, wbudowane buforowanie i obsługę HTTP/2. Według danych Square, 2025, OkHttp przetwarza miliardy zapytań dziennie w aplikacjach na całym świecie.

Najważniejsze

  • OkHttp — klient HTTP dla Android i Kotlin od Square z obsługą HTTP/2 i SPDY
  • Pula połączeń — mechanizm ponownego wykorzystania połączeń TCP w celu zmniejszenia opóźnień
  • Przechwytywacze Interceptor i NetworkInterceptor modyfikują zapytania i odpowiedzi
  • Buforowanie — wbudowany Cache zmniejsza ruch przy powtarzających się zapytaniach
  • WebSocket — obsługa komunikacji dwukierunkowej przez protokół WebSocket

Czym jest OkHttp?

OkHttp to wydajny klient HTTP dla Java, Android i Kotlin, opracowany przez firmę Square. Biblioteka udostępnia niskopoziomowe API do wykonywania zapytań HTTP z obsługą HTTP/2, SPDY, WebSocket i automatycznego odtwarzania połączeń w przypadku awarii sieci.

OkHttp pojawił się w 2013 roku jako odpowiedź na potrzebę niezawodnego klienta HTTP, który rozwiązałby problemy HttpURLConnection — brak puli połączeń, słabą obsługę HTTP/2 i niewygodne API. Do 2025 roku OkHttp jest używane na poziomie systemowym Android API: OkHttp jest wbudowane w implementację HttpURLConnection od Androida 4.4 (API 19).

Według danych Google I/O 2024, OkHttp przetwarza ponad 70% wszystkich zapytań HTTP w ekosystemie Androida. Jest to możliwe, ponieważ OkHttp stanowi warstwę transportową dla Retrofit, Apollo GraphQL, Firebase i wielu innych bibliotek. Programiści otrzymują funkcjonalność OkHttp automatycznie, bez jawnego dołączania go.

Jak działa OkHttp

Architektura OkHttp opiera się na łańcuchu przechwytywaczy (Interceptor chain). Każde zapytanie przechodzi przez sekwencję przechwytywaczy, które mogą modyfikować Request, Response lub przerwać wykonanie. Ta architektura przypomina wzorzec Chain of Responsibility i pozwala elastycznie rozszerzać funkcjonalność.

Gdy aplikacja wysyła zapytanie, OkHttp wykonuje następujące kroki: rozwiązuje DNS, wybiera połączenie z puli (lub tworzy nowe), otwiera uzgadnianie TLS (jeśli HTTPS), wysyła zapytanie HTTP, otrzymuje odpowiedź i zwraca ją do aplikacji. RealCall to wewnętrzna klasa zarządzająca pełnym cyklem życia zapytania od utworzenia do zakończenia.

OkHttp automatycznie obsługuje przekierowania (302, 301), ponawia zapytania w przypadku awarii sieci (retry), stosuje protokół keep-alive i obsługuje przezroczystą kompresję gzip. Programista nie musi pisać kodu dla tych operacji — OkHttp wykonuje je automatycznie na podstawie nagłówków serwera.

Obsługa HTTP/2 i multipleksowanie

HTTP/2 pozwala wysyłać wiele zapytań przez jedno połączenie TCP jednocześnie, bez blokowania (head-of-line blocking, charakterystyczne dla HTTP/1.1). OkHttp automatycznie używa HTTP/2, jeśli serwer obsługuje ten protokół, i przezroczysto przełącza się na HTTP/1.1 w razie potrzeby.

Multipleksowanie HTTP/2 jest szczególnie ważne dla aplikacji mobilnych, gdzie opóźnienie nawiązania połączenia (TCP + TLS) może wynosić 100–300 ms. Zamiast 10 kolejnych połączeń OkHttp używa jednego, zmniejszając całkowite opóźnienie o 40–60% na typowych urządzeniach z Androidem przy niestabilnym połączeniu.

Przechwytywacze OkHttp: Interceptor i NetworkInterceptor

Interceptor to interfejs z jedną metodą intercept(Chain), który otrzymuje Request, wykonuje działania i zwraca Response. Przechwytywacze są dwóch typów: przechwytywacze aplikacyjne (dodawane przez addInterceptor) i sieciowe (addNetworkInterceptor).

Przechwytywacze aplikacyjne uruchamiają się przed utworzeniem zapytania HTTP — widzą oryginalny Request i końcowy Response po wszystkich przekształceniach. Przechwytywacze sieciowe uruchamiają się na poziomie sieci: widzą zapytanie po kompresji gzip, dodaniu nagłówków Content-Length, przekierowaniach i ponownych próbach. Przechwytywacze sieciowe nie są wywoływane, jeśli odpowiedź pochodzi z pamięci podręcznej.

Typ przechwytywaczaMetoda dodawaniaKiedy wywoływanyWidzi pamięć podręczną
Application InterceptoraddInterceptor()Przed i po zapytaniuTak
Network InterceptoraddNetworkInterceptor()Na poziomie sieciNie

Zastosowanie przechwytywaczy w praktyce

W praktyce przechwytywacze OkHttp rozwiązują trzy główne zadania: autoryzację (dodawanie nagłówka Authorization), logowanie (HttpLoggingInterceptor do debugowania) i ponawianie (automatyczne powtarzanie zapytania przy awariach sieci). Łącząc kilka przechwytywaczy, można zbudować pełny pipeline przetwarzania zapytania bez powielania kodu w każdym wywołaniu HTTP aplikacji.

Kolejność dodawania przechwytywaczy ma znaczenie: Interceptor dodany jako pierwszy wykonuje się jako pierwszy na wejściu i jako ostatni na wyjściu. Dla NetworkInterceptor kolejność jest określana przez stos sieciowy. Zalecana kolejność: AuthInterceptor (dodaje token), LoggingInterceptor (loguje zapytanie), RetryInterceptor (ponawia przy awariach).

Logowanie przez HttpLoggingInterceptor

Do debugowania zapytań sieciowych używa się HttpLoggingInterceptor — gotowego przechwytywacza od Square. Loguje on metodę, URL, nagłówki i treść zapytania oraz odpowiedzi. Poziomy logowania: BASIC (metoda + URL + kod), HEADERS (z nagłówkami) i BODY (pełne zapytanie i odpowiedź). BODY jest przydatny podczas programowania, ale na produkcji jest wyłączany ze względów bezpieczeństwa i wydajności.

Przykłady kodu OkHttp w Kotlin

Rozważmy podstawowe zapytanie GET przez OkHttp. Najpierw tworzy się OkHttpClient — ciężki obiekt, który tworzy się raz i ponownie wykorzystuje. Następnie formułuje się Request z URL, a zapytanie jest wykonywane synchronicznie przez execute lub asynchronicznie przez 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())

Do wykonania asynchronicznego używa się metody enqueue, która przyjmuje Callback. OkHttp wykonuje zapytanie w tle i zwraca wynik w callbacku w tym samym wątku. Do przełączenia na główny wątek Androida użyj Handler lub korutyn.

kotlin
client.newCall(request).enqueue(object : Callback {
    override fun onFailure(
        call: Call, e: IOException
    ) {
        println("Żądanie nie powiodło się: ${e.message}")
    }

    override fun onResponse(
        call: Call, response: Response
    ) {
        println(response.body()?.string())
    }
})

Dodawanie przechwytywacza do autoryzacji

Niestandardowy Interceptor dodaje token Bearer do każdego zapytania. Przechwytywacz sprawdza obecność nagłówka Authorization, a jeśli token nie jest jeszcze ustawiony, dodaje go z magazynu. W przypadku odpowiedzi 401 przechwytywacz może odświeżyć token przez 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)
    }
}

Pula połączeń i buforowanie OkHttp

Pula połączeń (ConnectionPool) — kluczowa optymalizacja OkHttp, umożliwiająca ponowne wykorzystanie połączeń TCP dla wielu zapytań. Zamiast tworzyć nowy gniazdo dla każdego zapytania, OkHttp przechowuje do 5 nieaktywnych połączeń (domyślnie) przez 5 minut, co zmniejsza opóźnienie o 30–70% dla powtarzających się zapytań do tego samego hosta.

Buforowanie odpowiedzi jest realizowane przez klasę Cache. Aby włączyć buforowanie, wystarczy wskazać katalog i maksymalny rozmiar w OkHttpClient.Builder. OkHttp automatycznie buforuje odpowiedzi GET zgodnie z nagłówkami Cache-Control, Expires i ETag, zwracając buforowane dane bez zapytania sieciowego, jeśli nie są nieaktualne.

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

Prawidłowa konfiguracja puli i bufora jest szczególnie ważna dla aplikacji z częstymi zapytaniami — kanałów informacyjnych, czatów, aktualizacji danych. Bez puli każde połączenie TCP wymaga trójstronnego uzgadniania (SYN, SYN-ACK, ACK) i potencjalnie uzgadniania TLS (2–3 round-trip), co dodaje 100–500 ms do każdego zapytania.

OkHttp obsługuje również WebSocket przez klasę RealWebSocket. Połączenie WebSocket jest nawiązywane przez uzgadnianie HTTP (101 Switching Protocols), a następnie przełącza się na protokół dwukierunkowy. OkHttp automatycznie wysyła pakiety ping w celu utrzymania połączenia przy życiu i ponownie łączy się w przypadku zerwania. WebSocket od OkHttp jest kompatybilny ze standardowymi punktami końcowymi, takimi jak wss://echo.websocket.org.

Typowe błędy przy pracy z OkHttp

Tworzenie OkHttpClient dla każdego zapytania — najczęstszy błąd. OkHttpClient zawiera pulę połączeń, pamięć podręczną i pulę wątków. Tworzenie nowej instancji dla każdego zapytania nie tylko marnuje pamięć, ale także pozbawia korzyści z ponownego wykorzystania połączeń. OkHttpClient powinien być singletonem przez kontener DI.

Ignorowanie zamykania Response.body() prowadzi do wycieków zasobów. ResponseBody zawiera InputStream, który należy zamknąć po odczytaniu. Jeśli używane jest body().string() lub body().bytes(), OkHttp zamyka strumień automatycznie, ale przy odczycie body().byteStream() lub body().charStream() wymagane jest jawne wywołanie close() w bloku finally.

Brak obsługi limitu czasu — kolejny problem. Domyślnie OkHttp nie ma limitów czasu (connectTimeout = 10 sekund, readTimeout = 10 sekund, writeTimeout = 10 sekund). Dla aplikacji mobilnych z niestabilnym połączeniem zaleca się ustawienie connectTimeout 15–30 sekund i readTimeout 15–30 sekund, w przeciwnym razie użytkownik będzie czekał zbyt długo przy słabym sygnale.

Często zadawane pytania

Czym różni się OkHttp od Retrofit?

OkHttp to niskopoziomowy klient HTTP z ręcznym zarządzaniem Request i Response. Retrofit to wysokopoziomowa nakładka z adnotacjami. OkHttp jest używane jako transport dla Retrofit, ale może działać również samodzielnie bez dodatkowych bibliotek.

Jak OkHttp obsługuje HTTPS?

OkHttp używa SSLSocketFactory do uzgadniania TLS. Biblioteka obsługuje CertificatePinner do przypinania certyfikatów (Certificate Pinning), TrustManager do niestandardowej walidacji i HostnameVerifier do sprawdzania nazwy hosta względem certyfikatu.

Jak wychwycić błędy sieci w OkHttp?

Zapytania synchroniczne zgłaszają IOException w przypadku problemów z siecią. Zapytania asynchroniczne otrzymują wywołanie onFailure z IOException. Dla błędów HTTP (4xx, 5xx) odpowiedź jest uznawana za pomyślną — kod błędu sprawdza się przez response.isSuccessful().

Czy OkHttp obsługuje WebSocket?

Tak, OkHttp ma wbudowaną obsługę WebSocket przez klasę WebSocket i WebSocketListener. Po nawiązaniu połączenia WebSocket umożliwia wysyłanie i odbieranie wiadomości w czasie rzeczywistym bez ponownych zapytań HTTP.

Jak wyłączyć przekierowania w OkHttp?

Wyłącz automatyczne przekierowania przez followRedirects(false) i followSslRedirects(false) w OkHttpClient.Builder. Jest to przydatne, gdy trzeba ręcznie obsłużyć przekierowanie, na przykład w celu wyodrębnienia tokena z URL przekierowania.

Podsumowanie

  • OkHttp — wysokowydajny klient HTTP od Square z obsługą HTTP/2 i SPDY
  • Architektura przechwytywaczy realizuje Chain of Responsibility do modyfikacji zapytań
  • Pula połączeń ponownie wykorzystuje połączenia TCP, zmniejszając opóźnienie o 30–70%
  • Buforowanie Cache-Control i ETag zmniejszają ruch przy powtarzających się zapytaniach
  • WebSocket zapewnia dwukierunkową komunikację w czasie rzeczywistym
  • OkHttpClient powinien być singletonem — tworzenie dla każdego zapytania prowadzi do wycieków
  • ResponseBody wymaga jawnego zamknięcia przy strumieniowym odczycie byteStream

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również