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 |
| Retry | 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 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также