angular-interceptors
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseAngular HTTP Interceptors
Angular HTTP 拦截器
Version: Angular 21 (2025)
Tags: HTTP, Interceptors, Auth, Middleware
References: Interceptors Guide • API
API Changes
API 变更
This section documents recent version-specific API changes.
-
NEW: Functional interceptors — Useinstead of class-based
HttpInterceptorFn -
NEW: provideHttpClient with withInterceptors — Modern interceptor setup
-
NEW: HttpContext — Per-request metadata with HttpContextToken
-
DEPRECATED: Class-based HttpInterceptor — Migrate to functional
本节记录了近期特定版本的API变动:
-
新增:函数式拦截器 —— 使用替代基于类的拦截器
HttpInterceptorFn -
新增:搭配withInterceptors使用provideHttpClient —— 现代化拦截器配置方案
-
新增:HttpContext —— 基于HttpContextToken实现的单请求元数据
-
已废弃:基于类的HttpInterceptor —— 请迁移至函数式写法
Best Practices
最佳实践
- Create functional interceptor
ts
export const authInterceptor: HttpInterceptorFn = (req, next) => {
const authService = inject(AuthService);
const token = authService.getToken();
if (token) {
const authReq = req.clone({
setHeaders: { Authorization: `Bearer ${token}` }
});
return next(authReq);
}
return next(req);
};- Register interceptors
ts
export const appConfig: ApplicationConfig = {
providers: [
provideHttpClient(
withInterceptors([authInterceptor, logInterceptor])
)
]
};- Handle errors in interceptor
ts
export const errorInterceptor: HttpInterceptorFn = (req, next) => {
return next(req).pipe(
catchError((error: HttpErrorResponse) => {
if (error.status === 401) {
inject(Router).navigate(['/login']);
}
return throwError(() => error);
})
);
};- Use multiple interceptors (order matters)
ts
provideHttpClient(
withInterceptors([loggingInterceptor, authInterceptor, errorInterceptor])
)- Use HttpContext for per-request flags
ts
const CACHE_KEY = new HttpContextToken<boolean>(() => false);
export const cacheInterceptor: HttpInterceptorFn = (req, next) => {
if (req.context.get(CACHE_KEY)) {
// Check cache
}
return next(req);
};
// Usage
http.get('/api/data', { context: new HttpContext().set(CACHE_KEY, true) });- Transform request
ts
export const transformInterceptor: HttpInterceptorFn = (req, next) => {
if (req.url.includes('/api/')) {
const transformed = req.clone({
setHeaders: { 'X-Custom-Header': 'value' }
});
return next(transformed);
}
return next(req);
};- Transform response
ts
export const responseInterceptor: HttpInterceptorFn = (req, next) => {
return next(req).pipe(
map(event => {
if (event instanceof HttpResponse) {
return event.clone({ body: transformData(event.body) });
}
return event;
})
);
};- 创建函数式拦截器
ts
export const authInterceptor: HttpInterceptorFn = (req, next) => {
const authService = inject(AuthService);
const token = authService.getToken();
if (token) {
const authReq = req.clone({
setHeaders: { Authorization: `Bearer ${token}` }
});
return next(authReq);
}
return next(req);
};- 注册拦截器
ts
export const appConfig: ApplicationConfig = {
providers: [
provideHttpClient(
withInterceptors([authInterceptor, logInterceptor])
)
]
};- 在拦截器中处理错误
ts
export const errorInterceptor: HttpInterceptorFn = (req, next) => {
return next(req).pipe(
catchError((error: HttpErrorResponse) => {
if (error.status === 401) {
inject(Router).navigate(['/login']);
}
return throwError(() => error);
})
);
};- 使用多个拦截器(执行顺序和注册顺序一致)
ts
provideHttpClient(
withInterceptors([loggingInterceptor, authInterceptor, errorInterceptor])
)- 使用HttpContext设置单请求标记
ts
const CACHE_KEY = new HttpContextToken<boolean>(() => false);
export const cacheInterceptor: HttpInterceptorFn = (req, next) => {
if (req.context.get(CACHE_KEY)) {
// Check cache
}
return next(req);
};
// Usage
http.get('/api/data', { context: new HttpContext().set(CACHE_KEY, true) });- 转换请求
ts
export const transformInterceptor: HttpInterceptorFn = (req, next) => {
if (req.url.includes('/api/')) {
const transformed = req.clone({
setHeaders: { 'X-Custom-Header': 'value' }
});
return next(transformed);
}
return next(req);
};- 转换响应
ts
export const responseInterceptor: HttpInterceptorFn = (req, next) => {
return next(req).pipe(
map(event => {
if (event instanceof HttpResponse) {
return event.clone({ body: transformData(event.body) });
}
return event;
})
);
};