HTTP — случаи использования перехватчиков¶
08.11.2022
Ниже перечислены несколько распространенных случаев использования перехватчиков.
Установка заголовков по умолчанию¶
Приложения часто используют перехватчик для установки заголовков по умолчанию в исходящих запросах.
В примере приложения есть AuthService
, который производит токен авторизации. Вот его AuthInterceptor
, который инжектирует этот сервис для получения токена и добавляет заголовок авторизации с этим токеном к каждому исходящему запросу:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
Практика клонирования запроса для установки новых заголовков настолько распространена, что для этого существует ярлык setHeaders
:
1 2 3 4 |
|
Перехватчик, изменяющий заголовки, может быть использован для ряда различных операций, включая:
- Аутентификация/авторизация
- Поведение кэширования; например,
If-Modified-Since
. - XSRF защита
Регистрация пар запроса и ответа¶
Поскольку перехватчики могут обрабатывать запрос и ответ вместе, они могут выполнять такие задачи, как определение времени и протоколирование всей операции HTTP.
Рассмотрим следующий LoggingInterceptor
, который фиксирует время запроса, время ответа и записывает результат в журнал с указанием прошедшего времени с внедренным MessageService
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
|
Оператор RxJS tap
фиксирует, был ли запрос успешным или неудачным. Оператор RxJS finalize
вызывается, когда наблюдаемый ответ либо возвращает ошибку, либо завершается и сообщает о результате в MessageService
.
Ни tap
, ни finalize
не затрагивают значения потока наблюдаемых, возвращаемых вызывающей стороне.
Пользовательский парсинг JSON¶
Перехватчики могут быть использованы для замены встроенного парсинга JSON на пользовательскую реализацию.
Перехватчик CustomJsonInterceptor
в следующем примере демонстрирует, как этого добиться. Если перехватываемый запрос ожидает ответ в формате 'json'
, то responseType
изменяется на 'text'
, чтобы отключить встроенный парсинг JSON.
Затем ответ разбирается с помощью внедренного JsonParser
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
|
Затем вы можете реализовать свой собственный пользовательский JsonParser
. Вот пользовательский JsonParser, который имеет специальное средство восстановления даты.
1 2 3 4 5 6 7 8 9 10 |
|
Вы предоставляете CustomParser
вместе с CustomJsonInterceptor
.
1 2 |
|
Кэширование запросов¶
Перехватчики могут обрабатывать запросы самостоятельно, без переадресации на next.handle()
.
Например, вы можете решить кэшировать определенные запросы и ответы для повышения производительности. Вы можете делегировать кэширование перехватчику, не нарушая работу существующих служб данных.
Перехватчик CachingInterceptor
в следующем примере демонстрирует этот подход.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
-
Функция
isCacheable()
определяет, является ли запрос кэшируемым.В данном примере кэшируемыми являются только GET-запросы к API поиска пакетов.
-
Если запрос не является кэшируемым, перехватчик пересылает запрос следующему обработчику в цепочке.
-
Если кэшируемый запрос найден в кэше, перехватчик возвращает
of()
observable с кэшированным ответом, минуя обработчикnext
и все другие перехватчики ниже по течению -
Если кэшируемый запрос не находится в кэше, код вызывает
sendRequest()
.Эта функция передает запрос в
next.handle()
, который в конечном итоге вызывает сервер и возвращает ответ сервера.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
Обратите внимание, как sendRequest()
перехватывает ответ на обратном пути к приложению. Этот метод передает ответ через оператор tap()
, обратный вызов которого добавляет ответ в кэш.
Исходный ответ продолжает нетронутым возвращаться по цепочке перехватчиков к вызывающему приложению.
Службы данных, такие как PackageSearchService
, не знают, что некоторые из их запросов HttpClient
на самом деле возвращают кэшированные ответы.
Используйте перехватчики для запроса нескольких значений¶
Метод HttpClient.get()
обычно возвращает наблюдаемую, которая выдает одно значение, либо данные, либо ошибку. Перехватчик может изменить это на наблюдаемую, которая выдает несколько значений.
Следующая измененная версия CachingInterceptor
по желанию возвращает наблюдаемую, которая немедленно выдает кэшированный ответ, посылает запрос API поиска пакетов и выдает его позже с обновленными результатами поиска.
1 2 3 4 5 6 7 8 9 10 11 |
|
Опция cache-then-refresh срабатывает при наличии пользовательского заголовка x-refresh
.
Флажок на PackageSearchComponent
устанавливает флаг withRefresh
, который является одним из аргументов метода PackageSearchService.search()
. Этот метод search()
создает пользовательский заголовок x-refresh
и добавляет его в запрос перед вызовом HttpClient.get()
.
Переработанный CachingInterceptor
устанавливает запрос на сервер независимо от того, есть ли кэшированное значение или нет, используя тот же метод sendRequest()
, который описан выше. Наблюдаемая results$
выполняет запрос при подписке.
-
Если нет кэшированного значения, перехватчик возвращает
results$
. -
Если есть кэшированное значение, код переводит кэшированный ответ на
results$
. В результате создается перекомпонованная наблюдаемая, которая выдает два ответа, поэтому подписчики будут видеть последовательность этих двух ответов:-
кэшированный ответ, который выдается немедленно.
-
Ответ от сервера, который выдается позже.
-