angular-interceptors

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Angular HTTP Interceptors

Angular HTTP 拦截器

Version: Angular 21 (2025) Tags: HTTP, Interceptors, Auth, Middleware
References: Interceptors GuideAPI
版本: Angular 21(2025年) 标签: HTTP, Interceptors, Auth, Middleware
参考资料: 拦截器指南API文档

API Changes

API 变更

This section documents recent version-specific API changes.
  • NEW: Functional interceptors — Use
    HttpInterceptorFn
    instead of class-based
  • 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;
    })
  );
};