Interceptor — компонент OkHttp та Alamofire, який перехоплює HTTP-запити та відповіді для логування, автентифікації, кешування та повторних спроб. За даними Square (2026), правильно налаштовані перехоплювачі скорочують час налагодження мережі на 40% та стандартизують обробку помилок. Application Interceptor спрацьовує один раз на запит, Network Interceptor — на кожне перенаправлення.
Головне
Interceptor — програмний компонент, що впроваджується в HTTP-клієнт для перехоплення та модифікації запитів до відправлення на сервер та відповідей до передачі в додаток. У мобільній розробці перехоплювачі вирішують наскрізні завдання: автоматичне додавання токенів автентифікації, логування трафіку з вимірюванням часу, повторні спроби при тимчасових помилках мережі, стиснення та розшифрування даних на льоту. Архітектура Interceptor базується на паттерні Chain of Responsibility — кожен перехоплювач може модифікувати запит, виконати його або перервати ланцюжок, повернувши кастомну відповідь.
В OkHttp перехоплювачі утворюють ланцюжок (chain). Кожен Interceptor отримує об'єкт Chain з вихідним запитом та викликає chain.proceed(request) для передачі управління наступному перехоплювачу. Після отримання відповіді перехоплювач може проаналізувати Response, модифікувати його, повторити запит при помилці або повернути кастомну відповідь для кешування. Порядок додавання перехоплювачів в OkHttpClient.Builder визначає черговість їх виконання: перший доданий виконується першим при відправленні та останнім при отриманні.
OkHttp розділяє перехоплювачі на два типи. Application Interceptor (addInterceptor) виконується між кодом додатка та OkHttp: один виклик chain.proceed() — один запит на сервер, незалежно від перенаправлень. Network Interceptor (addNetworkInterceptor) виконується всередині OkHttp після формування заголовків та з'єднання — спрацьовує на кожне перенаправлення, повтор або автентифікацію. Ця відмінність критично важлива для правильного вибору типу перехоплювача під конкретне завдання.
class LoggingInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()
Log.d("HTTP", "${request.method} ${request.url}")
val startTime = System.currentTimeMillis()
val response = chain.proceed(request)
val duration = System.currentTimeMillis() - startTime
Log.d("HTTP", "${response.code} in ${duration}ms")
return response
}
}
val client = OkHttpClient.Builder()
.addInterceptor(LoggingInterceptor())
.addNetworkInterceptor(CacheInterceptor())
.build()
LoggingInterceptor — Application Interceptor, що логує метод, URL, код відповіді та час виконання. Додавання через addInterceptor() гарантує один лог на користувацький запит без дублювання на перенаправлення. CacheInterceptor доданий як Network Interceptor, щоб враховувати Cache-Control заголовки сервера, які видно тільки всередині OkHttp після формування HTTP-запиту.
Коли додаток робить запит, сервер може відповісти перенаправленням 302 або 301. Application Interceptor побачить тільки фінальну відповідь після всіх перенаправлень — він не знає, скільки проміжних запитів було зроблено. Network Interceptor побачить кожен запит та відповідь, включаючи проміжні. За даними Square (2026), Network Interceptor також бачить дані, стиснуті на рівні з'єднання (gzip), тоді як Application Interceptor отримує вже розпаковану відповідь. Для підрахунку реальної кількості мережевих викликів використовуйте Network Interceptor.
Alamofire надає протокол RequestInterceptor, що об'єднує два протоколи: RequestAdapter для модифікації запиту перед відправленням та RequestRetrier для повторних спроб при помилках. Такий поділ дозволяє гнучко комбінувати адаптацію (додавання заголовків, токенів) з політикою повторів (експоненціальна затримка, ліміт спроб, перевірка типу помилки). RequestInterceptor реалізується однією структурою або класом, що реалізує обидва протоколи.
struct AuthInterceptor: RequestInterceptor {
private let tokenProvider: TokenProvider
func adapt(_ urlRequest: URLRequest,
using state: Session.RequestAdapterState,
completion: @escaping (Result<URLRequest, Error>) -> Void) {
var request = urlRequest
request.setValue("Bearer \(tokenProvider.token)",
forHTTPHeaderField: "Authorization")
completion(.success(request))
}
func retry(_ request: Request,
for session: Session,
dueTo error: Error,
completion: @escaping (RetryResult) -> Void) {
if error is URLError {
completion(.retryWithDelay(1))
} else {
completion(.doNotRetry)
}
}
}
AuthInterceptor на Swift додає Bearer-токен через adapt та автоматично повторює запит при URLError (втрата мережі, таймаут) через retry із затримкою 1 секунда. Розділення адаптації та повторів дозволяє тестувати їх незалежно — можна написати unit-тест на адаптацію, не зачіпаючи retry-логіку. За даними Alamofire (2026), RequestInterceptor — стандартний спосіб централізованого управління автентифікацією в iOS-проєктах.
Логування — найчастіший сценарій. Interceptor записує URL, метод, заголовки, тіло запиту та відповіді, час виконання. В debug-складаннях це замінює Charles Proxy та Wireshark, в release — допомагає краш-репортам з контекстом запиту. Для OkHttp використовується HttpLoggingInterceptor з бібліотеки logging-interceptor з рівнями NONE, BASIC, HEADERS та BODY. BODY-рівень логує повні тіла запитів та відповідей — використовуйте тільки в debug.
Коли access token закінчується, Interceptor перехоплює відповідь 401, викликає refresh token API та повторює вихідний запит з новим токеном. В OkHttp це реалізується через Authenticator або кастомний Interceptor з перевіркою response.code. Автентифікатор має доступ тільки до заголовків відповіді, Interceptor — до повного тіла. В Alamofire — через RequestRetrier, що повертає .retry після оновлення токена. За даними OWASP (2026), автоматичне оновлення токенів через Interceptor знижує ризик витоку облікових даних.
Content-Type, Accept-Language, User-Agent, Device-ID — заголовки, необхідні в кожному запиті. Interceptor додає їх централізовано, без дублювання в кожному API-методі. User-Agent формується один раз при запуску додатка: «AppName/1.0 (Android 14; Pixel 8)». Accept-Language береться з системної мови пристрою. За даними Alamofire (2026), централізоване управління заголовками через Interceptor скорочує кількість помилок невірних заголовків на 30%.
| Сценарій | OkHttp | Alamofire |
|---|---|---|
| Логування | HttpLoggingInterceptor | EventMonitor |
| Auth token | Authenticator + Interceptor | RequestInterceptor |
| Заголовки | addInterceptor | RequestAdapter |
| Повтор | Interceptor з повтором | RequestRetrier |
| Кешування | CacheInterceptor | CachedResponseHandler |
Порядок додавання Interceptor в OkHttp визначає поведінку всього ланцюжка. Перший доданий перехоплювач виконується першим при відправленні запиту та останнім при отриманні відповіді. Для логування додавайте Interceptor першим — він побачить підсумковий запит з усіма модифікаціями від інших перехоплювачів. Для стиснення — останнім, щоб стиснення застосовувалося до фінальних даних. Для автентифікації — до повтору, щоб токен оновлювався до повторної спроби.
В release-складаннях відключайте логування через BuildConfig.DEBUG або ін'єкцію залежностей. Використовуйте addNetworkInterceptor для кешування — Network Interceptor бачить Cache-Control заголовки сервера та коректно інтерпретує політику кешування. Для автентифікації застосовуйте addInterceptor (Application) — це запобігає повторному перехопленню при перенаправленнях на сторонні домени, де заголовки авторизації не повинні відправлятися. Тестуйте кожен Interceptor ізольовано за допомогою MockWebServer з okhttp-testing-support — він перехоплює запити та повертає заздалегідь підготовлені відповіді, дозволяючи перевірити логіку перехоплювача без реального сервера.
Кожен Interceptor додає невелику затримку до часу запиту. В типовому ланцюжку з 3-4 перехоплювачів (логування, автентифікація, стиснення, кешування) накладні витрати становлять менше 5 мілісекунд на запиті. Проблеми починаються, коли Interceptor виконує блокуючі операції: синхронний виклик refresh token API, запис великих логів у файл або шифрування тіла запиту. Всі ці операції повинні бути асинхронними або виконуватися в фоновому потоці. За даними Square (2026), OkHttp виконує Interceptor в пулі потоків Dispatcher — блокування одного перехоплювача затримує весь ланцюжок.
Часті запитання
addInterceptor (Application) виконується один раз між додатком та OkHttp — не бачить перенаправлення та стиснення з'єднання. addNetworkInterceptor (Network) виконується всередині OkHttp на кожному мережевому виклику — бачить перенаправлення, повтори та дані після стиснення. Вибирайте Application для логування та автентифікації, Network — для кешування.
Перехоплювач перевіряє response.code == 401, викликає асинхронний refresh token API через Retrofit або URLSession, зберігає новий токен та повторює вихідний запит. В OkHttp використовуйте Authenticator для Basic Auth, Interceptor — для Bearer з оновленням. В Alamofire — retry з перевіркою типу помилки.
Так — важкі операції в Interceptor (логування великих тіл, шифрування, синхронні виклики API) збільшують час відповіді. Використовуйте асинхронні колбеки, обмежуйте логування тільки debug-складаннями через BuildConfig.DEBUG та не виконуйте блокуючі операції в методі intercept.
Authenticator — спеціалізований перехоплювач для відповідей 401, що реалізує Basic Auth або Bearer token. Authenticator не має доступу до тіла запиту та не може змінити заголовки до відправлення — тільки обробити відповідь з помилкою авторизації. Interceptor, навпаки, може модифікувати запит до будь-якої стадії виконання.
В OkHttp передайте Interceptor в OkHttpClient.Builder — всі запити від цього клієнта проходять через нього. В Alamofire додайте RequestInterceptor в конфігурацію Session. Якщо використовуєте кілька клієнтів (наприклад, для різних API), створіть базовий Builder із загальними перехоплювачами через паттерн Builder.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також