Разработчик, который впервые видит в логах приложения или в коде коллег слово interceptor, обычно сталкивается с одной и той же ситуацией: запрос к серверу «волшебным образом» дополняется токеном авторизации, хотя в самом коде запроса этого кода нет. Причина именно в перехватчике — это компонент, который встраивается в цепочку обработки запроса или ответа и выполняет свою логику до того, как данные дойдут до адресата.
Interceptor (перехватчик) — это программный механизм, который «перехватывает» вызовы, запросы или события на пути от отправителя к получателю, позволяя изменить, дополнить, залогировать или заблокировать их, не меняя основной код. Концепция используется в веб-разработке, мобильных приложениях, сетевых библиотеках и даже в операционных системах. Ниже разберём, как это работает, где применяется и чем перехватчик отличается от похожих механизмов.
Как работает interceptor: общий принцип
Принцип работы перехватчика проще всего представить как «таможенный пост» на дороге. Запрос (например, HTTP-запрос к API) — это автомобиль, а interceptor — пост, на котором машину останавливают, проверяют документы, могут догрузить что-то в багажник и только потом пропускают дальше. На обратном пути, когда приходит ответ от сервера, перехватчик снова может вмешаться: например, расшифровать данные или обработать ошибку.
Технически это реализуется через цепочку обработчиков (chain). Перехватчик получает объект запроса, выполняет свою логику и вызывает следующий элемент цепочки. Если перехватчиков несколько, они образуют конвейер: каждый по очереди получает управление. Важно понимать, что перехватчик имеет доступ и к запросу, и к ответу — это отличает его от простых фильтров, которые часто работают только в одну сторону.
Interceptor — это «прослойка» между клиентом и сервером, которая может читать и изменять запросы и ответы, не затрагивая основной код приложения.
Где применяются перехватчики
Чаще всего термин встречается в контексте сетевого взаимодействия, но область применения шире. Вот основные сценарии, где перехватчики используются постоянно:
- 🔑 Авторизация — автоматическое добавление токена (например,
Authorization: Bearer ...) к каждому исходящему запросу. - 📝 Логирование — запись всех запросов и ответов для отладки, без вставки кода логирования в каждый метод.
- 🔄 Обработка ошибок — централизованный перехват ответов с кодами 401, 403, 500 и единая реакция на них (например, обновление токена или редирект на страницу входа).
- 📦 Трансформация данных — сжатие, шифрование, изменение формата тела запроса или ответа «на лету».
- ⏱️ Кэширование и повторные попытки — автоматический retry при сетевом сбое или отдача закэшированного ответа.
Помимо HTTP, концепция перехвата встречается в ORM-фреймворках (перехват событий сохранения сущности), в библиотеках внедрения зависимостей и в системных вызовах. Общая идея везде одна: вмешательство в стандартный поток выполнения без его переписывания.
Interceptor в популярных фреймворках
Во фронтенд-разработке перехватчики наиболее известны по Angular. Там они реализуются через интерфейс HttpInterceptor и регистрируются в механизме внедрения зависимостей. Классический сценарий — добавление JWT-токена из хранилища ко всем исходящим запросам и перехват ответа с ошибкой 401 для обновления токена. Точные детали API зависят от версии фреймворка, поэтому перед реализацией стоит свериться с официальной документацией используемой версии.
В Android-разработке де-факто стандартом является OkHttp, где перехватчики делятся на два типа: application interceptors (работают на уровне приложения, видят запрос до механизмов повторов и редиректов) и network interceptors (работают на уровне сети, видят каждый фактический сетевой вызов). Упрощённый пример на Kotlin:
val client = OkHttpClient.Builder()
.addInterceptor { chain ->
val request = chain.request().newBuilder()
.addHeader("Authorization", "Bearer $token")
.build()
chain.proceed(request)
}
.build()
В экосистеме JavaScript популярная библиотека Axios предоставляет axios.interceptors.request и axios.interceptors.response — отдельные точки подключения для исходящих запросов и входящих ответов. В бэкенд-фреймворках, например в NestJS или Spring, существуют свои аналогичные механизмы с похожей семантикой.
Чем interceptor отличается от middleware и фильтров
Эти термины часто путают, потому что все они описывают «прослойки» в обработке запроса. Разница в основном терминологическая и зависит от экосистемы, но общую картину можно свести к таблице:
| Механизм | Где работает | Типичная задача |
|---|---|---|
| Interceptor | Клиентские HTTP-библиотеки, DI-контейнеры | Модификация запросов и ответов, токены, логи |
| Middleware | Серверные фреймворки (Express, ASP.NET) | Обработка входящего запроса до маршрутизации |
| Filter | Сервлеты Java, некоторые веб-фреймворки | Предобработка запроса/ответа на уровне контейнера |
| Proxy | Сетевая инфраструктура, объекты-заместители | Замещение объекта или узла, контроль доступа |
На практике границы размыты: один и тот же приём в разных фреймворках может называться по-разному. Ключевой признак interceptor — доступ к обеим сторонам обмена (запросу и ответу) и возможность их изменять в единой цепочке.
Если вы проектируете обработку ошибок API, выносите её в один перехватчик, а не дублируйте в каждом вызове — так логика останется в одном месте и её будет проще менять.
Типичные задачи и реализация: порядок действий
Рассмотрим безопасный и универсальный порядок добавления перехватчика на примере задачи «добавлять токен ко всем запросам». Конкретный синтаксис зависит от вашей библиотеки, но шаги общие:
- 🧭 Определите, в какой точке нужен перехват: до отправки запроса, после получения ответа или в обоих местах.
- 🧩 Создайте функцию или класс перехватчика по правилам вашей библиотеки (интерфейс, callback, декоратор).
- 🔐 Реализуйте логику: чтение токена из хранилища, добавление заголовка, обработку ошибок. Не зашивайте секреты в код.
- 🔗 Зарегистрируйте перехватчик в клиенте или контейнере зависимостей.
- 🧪 Проверьте работу: в инструментах разработчика браузера или в сниффере трафика должен быть виден добавленный заголовок.
☑️ Проверка работы перехватчика
⚠️ Внимание: перехватчик, который изменяет тело запроса или ответа, может незаметно сломать приложение, если логика выбрасывает исключение. Всегда обрабатывайте ошибки внутри перехватчика и гарантированно передавайте управление дальше по цепочке — иначе запрос «зависнет» без ответа.
Типичные ошибки при работе с перехватчиками
Первая и самая частая проблема — бесконечный цикл. Если перехватчик при ошибке 401 сам выполняет запрос на обновление токена через тот же клиент, этот запрос тоже пройдёт через перехватчик, и при неудаче цикл повторится. Решение — помечать служебные запросы или использовать отдельный экземпляр клиента без перехватчика.
Вторая ошибка — нарушение порядка в цепочке. Если перехватчик логирования стоит до перехватчика авторизации, в лог попадут запросы без токена, что может ввести в заблуждение при отладке. Порядок регистрации перехватчиков имеет значение, и его нужно продумывать осознанно.
⚠️ Внимание: не логируйте в перехватчике тела запросов с паролями, токенами или персональными данными в открытом виде. Логи часто попадают в системы мониторинга и архивы, к которым имеют доступ люди, не связанные с разработкой.
Interceptor вне программирования
Слово interceptor имеет и другие значения. В авиации так называют самолёт-перехватчик — истребитель, задача которого быстро подняться и перехватить воздушную цель. В автомобильной тематике Interceptor — известная модель Jensen Interceptor, а также название, ассоциируемое с полицейскими версиями автомобилей Ford. В канализационной технике interceptor — это ловушка-сепаратор для жиров или нефтепродуктов. Контекст запроса определяет, какое значение имеется в виду; в IT-среде почти всегда речь идёт о программном перехватчике запросов.
Когда перехватчик не нужен
Не каждую задачу стоит решать через interceptor. Если логика касается одного конкретного запроса — например, уникальный заголовок для единственного вызова — проще и чище передать её прямо в месте вызова. Перехватчик оправдан, когда поведение должно быть сквозным: одинаковым для всех или большинства запросов приложения.
Также стоит воздержаться от перехватчиков, если команда не готова поддерживать «невидимую» логику. Код в перехватчике не виден в точке вызова, и новичок в проекте может долго искать, откуда берётся тот или иной заголовок. Хорошая практика — документировать зарегистрированные перехватчики и держать их список коротким.
Используйте interceptor для сквозных задач (токены, логи, ошибки), а разовую логику оставляйте в точке вызова — так код останется предсказуемым.
Часто задаваемые вопросы
Чем interceptor отличается от middleware?
Терминологически — экосистемой: middleware чаще называют серверные прослойки, обрабатывающие входящие запросы, а interceptor — клиентские перехватчики исходящих запросов и входящих ответов. Функционально идея одна: вмешательство в стандартный поток обработки.
Может ли перехватчик полностью отменить запрос?
Да. Перехватчик может не передавать управление дальше по цепочке и вместо этого вернуть собственный ответ — например, данные из кэша или ошибку валидации. Это штатная возможность в большинстве реализаций.
Сколько перехватчиков можно добавить к одному клиенту?
Жёсткого ограничения обычно нет — они выстраиваются в цепочку и выполняются последовательно. Однако каждый перехватчик добавляет накладные расходы и усложняет отладку, поэтому на практике их держат немного: авторизация, логирование, обработка ошибок.
Безопасно ли хранить токен внутри перехватчика?
Сам перехватчик токен не хранит — он лишь читает его из хранилища (память, защищённое хранилище платформы) в момент запроса. Вопрос безопасности относится к способу хранения токена, а не к механизму перехвата. Зашивать токен прямо в код перехватчика нельзя.
Что означает interceptor в авиации?
В авиации это самолёт-перехватчик — скоростной истребитель, предназначенный для быстрого подъёма и перехвата воздушных целей. Это значение не связано с программированием, хотя метафора общая: «перехват» объекта на пути к цели.