HTTP-интерцепторы в Angular — это механизм перехвата и обработки всех
исходящих HTTP-запросов и входящих HTTP-ответов, выполняемых через
HttpClient. Они позволяют централизованно реализовывать
сквозную логику, не дублируя код в каждом сервисе работы с API.
Интерцепторы применяются для:
Интерцептор не заменяет сервисы API, а дополняет их, работая на уровне инфраструктуры.
Все HTTP-запросы в Angular проходят через цепочку интерцепторов. Эта цепочка формируется в порядке регистрации провайдеров.
Пайплайн выглядит следующим образом:
HttpClientКаждый интерцептор может:
Интерцептор представляет собой сервис, реализующий интерфейс
HttpInterceptor.
import { Injectable } from '@angular/core';
import {
HttpEvent,
HttpHandler,
HttpInterceptor,
HttpRequest
} from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable()
export class ExampleInterceptor implements HttpInterceptor {
intercept(
req: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
return next.handle(req);
}
}
Ключевые элементы:
HttpRequest — неизменяемый объект запросаHttpHandler — следующий обработчик в цепочкеnext.handle() — обязательный вызов для продолжения
цепочкиHttpRequest является immutable-объектом. Любое изменение
выполняется через метод clone().
const modifiedRequest = req.clone({
setHeaders: {
Authorization: 'Bearer TOKEN'
}
});
Попытка изменить исходный объект приведёт к ошибке компиляции или игнорированию изменений.
Интерцепторы регистрируются через DI-провайдер
HTTP_INTERCEPTORS.
import { HTTP_INTERCEPTORS } from '@angular/common/http';
@NgModule({
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: ExampleInterceptor,
multi: true
}
]
})
export class AppModule {}
Ключевой параметр:
Без multi: true предыдущие интерцепторы будут
перезаписаны.
Порядок регистрации определяет порядок обработки запроса:
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: FirstInterceptor, multi: true },
{ provide: HTTP_INTERCEPTORS, useClass: SecondInterceptor, multi: true }
]
First → Second → серверсервер → Second → FirstЭто важно при работе с логированием, авторизацией и обработкой ошибок.
Один из самых распространённых сценариев — автоматическое добавление токена.
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler) {
const token = localStorage.getItem('token');
if (!token) {
return next.handle(req);
}
const authReq = req.clone({
setHeaders: {
Authorization: `Bearer ${token}`
}
});
return next.handle(authReq);
}
}
Особенности:
Интерцепторы удобны для глобальной обработки ошибок через RxJS.
import { catchError } from 'rxjs/operators';
import { throwError } from 'rxjs';
@Injectable()
export class ErrorInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler) {
return next.handle(req).pipe(
catchError(error => {
if (error.status === 401) {
// обработка ошибки авторизации
}
if (error.status === 500) {
// серверная ошибка
}
return throwError(() => error);
})
);
}
}
Преимущества:
catchError в каждом
сервисеИнтерцепторы позволяют отслеживать весь HTTP-трафик.
@Injectable()
export class LoggingInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler) {
console.log('Request:', req);
return next.handle(req).pipe(
tap(event => {
console.log('Response:', event);
})
);
}
}
Часто используется только в режиме разработки и отключается для production-сборок.
Глобальный loader реализуется без привязки к конкретным компонентам.
@Injectable()
export class LoaderInterceptor implements HttpInterceptor {
private requests = 0;
intercept(req: HttpRequest<any>, next: HttpHandler) {
this.requests++;
return next.handle(req).pipe(
finalize(() => {
this.requests--;
if (this.requests === 0) {
// скрыть индикатор
}
})
);
}
}
Позволяет учитывать параллельные запросы и избегать преждевременного скрытия индикатора.
Иногда требуется пропустить интерцептор для определённых запросов.
Пример с кастомным заголовком:
if (req.headers.has('skip-auth')) {
const cleanReq = req.clone({
headers: req.headers.delete('skip-auth')
});
return next.handle(cleanReq);
}
Или проверка URL:
if (req.url.includes('/public')) {
return next.handle(req);
}
Это позволяет гибко управлять поведением без создания отдельных
HttpClient-экземпляров.
Интерцепторы подходят для простого кеширования GET-запросов.
@Injectable()
export class CacheInterceptor implements HttpInterceptor {
private cache = new Map<string, HttpEvent<any>>();
intercept(req: HttpRequest<any>, next: HttpHandler) {
if (req.method !== 'GET') {
return next.handle(req);
}
const cached = this.cache.get(req.urlWithParams);
if (cached) {
return of(cached);
}
return next.handle(req).pipe(
tap(event => {
this.cache.set(req.urlWithParams, event);
})
);
}
}
Подходит для:
Интерцепторы Angular:
Middleware:
HTTP-интерцепторы формируют инфраструктурный слой приложения. Они обеспечивают единый контроль над сетевым взаимодействием, повышают поддерживаемость кода и позволяют изолировать повторяющуюся техническую логику от прикладных сервисов.