Angular 拦截器

2022-05-24  本文已影响0人  品品下午茶

在 Angular 应用中,HttpClient 负责处理 HTTP 请求的发送和响应的接收。如果我们需要为发出的每一个请求,增加一个请求头信息(例如,访问令牌),那么,我们可能需要为每个请求发送方法添加相同的一段代码。

getBooks(): Observable<Book[]> {
  return this.http.get<Book[]>(this.booksUrl, {
    headers: new HttpHeaders({'Authorization': accessToken'})
  });
}

很快,这个方法会让代码变得臃肿,难于测试和维护。Angular 提供了拦截器,可以优雅地解决这个问题。

应用场景

Angular 的拦截器可以在下列场景下使用:

拦截器

在 Angular 应用中,拦截器是一个实现了 HttpInterceptor 接口的服务类。每个拦截器都要实现 HttpInterceptor 接口定义的 intercept() 方法。在 intercept() 方法中,可以对 HTTP 请求进行识别和处理。

HttpInterceptor 接口定义:

interface HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>
}

拦截器的定义:

/** Pass untouched request through to the next request handler. */
@Injectable()
export class SomeInterceptor implements HttpInterceptor {

  intercept(req: HttpRequest<any>, next: HttpHandler):
    Observable<HttpEvent<any>> {
    return next.handle(req);
  }
}

创建拦截器

现在,我们创建一个拦截器,为每一个发出的 HTTP 请求,在其请求头中添加一个访问令牌。

  1. 使用 Angular CLI 命令,创建一个认证拦截器。
ng generate interceptor authn

刚刚创建的拦截器:

import { Injectable } from '@angular/core';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor
} from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable()
export class AuthnInterceptor implements HttpInterceptor {

  constructor() {}

  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    return next.handle(request);
  }
}
  1. 注册 authn 拦截器。拦截器需要注册后,才可以使用。下面,在 AppModule 中,对其进行注册。
...
@NgModule({
  imports: [
...
    HttpClientModule,
...
  ],
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: AuthnInterceptor, multi: true }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

如果一个模块需要注册拦截器,那该模块必须导入 HttpClientModule 模块。

在注册拦截器时,我们使用了 multi 属性,并设置其值为 true. multi: true,表示当前注册的拦截器,可以实例化多个实例对象。

  1. 实现接口 intercept 方法。
  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    const authnReq = request.clone({
      setHeaders: {
        Authorization: 'accessToken'
      }
    });
    return next.handle(authnReq);
  }

因为作为参数的 HttpRequest 对象是不可以修改的,所以要修改 request 对象,就需要使用他的 clone 方法创建一个新的请求对象。同理, HttpHeaders 对象也不可以修改,需要使用 setHeaders 方法进行更新。

上一篇 下一篇

猜你喜欢

热点阅读