Angular Http 拦截器

2024 年 8 月 29 日 | 阅读 6 分钟

拦截并处理 HttpRequest 或 HttpResponse。

大多数拦截器会在将请求传递给链中的下一个拦截器之前转换传出的请求。处理(转换后的请求)。拦截器还可以通过将 RxJS 运算符应用于 next.take care() 返回的流来修改响应事件流。

拦截器很少会完全处理请求并创建一个新的事件流,而不是调用 nextHandle()。这是可接受的行为,但请注意,后续的拦截器将完全被跳过。

拦截器为单个请求返回事件流中的多个响应是罕见但有效的。

方法

参数

req HttpRequest 要处理的传出请求对象。

next HttpHandler 链中的下一个拦截器,或者在链中没有剩余拦截器时为后端。

返回值

Observable<Http Event<any>>: 事件流的可观察对象。

用法说明

要为整个应用程序使用 HttpInterceptors 的同一个实例,只需将 HttpClientModule 导入到你的 AppModule 中,并将拦截器添加到根应用程序注入器。假设你在不同的模块(例如,在延迟加载模块中)中多次导入 HttpClientModule。在这种情况下,每次导入都会创建一个 HttpClientModule 的新副本,该副本会覆盖在路由模块中提供的拦截器。

创建拦截器

目标是在任何 HTTP 请求中包含发送到本地存储的 JWT 作为 Authorization 标头。第一步是构建拦截器。为此,创建一个可注入的类,该类实现 HttpInterceptor。

任何我们想要创建的拦截器都需要实现 HttpInterceptor 接口。这意味着我们的新类应该有一个名为 intercept 的方法,其参数为 HttpRequest 和 HttpHandler。拦截器的使用会转换传出的请求和传入的响应,但我们不能篡改原始请求——它必须是不可变的。为了进行更改,我们需要克隆原始请求。

当我们克隆原始请求时,我们可以设置任何我们想要的标头。在我们的例子中,这非常简单——我们想通过调用 AuthService 的 getToken 方法从本地存储中获取的 JSON Web Token 后,添加一个带有 Bearer 授权方案的 Authorization 标头。

调用 forward.Handle 意味着我们将控制权传递给链中的下一个拦截器,如果存在的话。

将拦截器添加到 providers。

需要将拦截器添加到 HTTP_INTERCEPTORS 数组中。这是通过使用我们创建的新类转换现有的 HTTP_INTERCEPTORS 数组来完成的。将其添加到我们应用程序模块的 ProvidersArray 中。

任何我们想要创建的拦截器都需要实现 HttpInterceptor 接口.

这意味着我们的新类应该有一个名为 intercept 的方法,其参数为 HttpRequest 和 HttpHandler。拦截器的使用会转换传出的请求和传入的响应,但我们不能篡改原始请求——它必须是不可变的。为了进行更改,我们需要克隆原始请求。

当我们克隆原始请求时,我们可以设置任何我们想要的标头。在我们的例子中,这非常简单——我们想通过调用 AuthService 的 getToken 方法从本地存储中获取的 JSON Web Token 后,添加一个带有 Bearer 授权方案的 Authorization 标头。

将拦截器添加到 providers。

需要将拦截器添加到 HTTP_INTERCEPTORS 数组中。这是通过使用我们创建的新类转换现有的 HTTP_INTERCEPTORS 数组来完成的。将其添加到我们应用程序模块的 ProvidersArray 中。

现在,当我们进行任何 HTTP 请求时,用户的令牌将自动附加。

此请求将包含一个 Authorization 标头,其值为 Bearer I。

需要注意的是,这里使用的是 Angular 新的 HttpClient(来自 @angular/common/http),而不是 @angular/http 中的 Http 类。如果我们尝试使用传统的 HttpClass 进行请求,拦截器将不会被命中。

查找未授权响应

当令牌过期时,我们通常会从服务器收到 401 Unauthorized 响应。这表明我们需要用户重新登录才能获取新令牌。

此时,我们有几个选项。我们是想重定向到具有登录表单的特定路由吗?我们是想显示一个模态框吗?我们是想尝试刷新令牌吗?

intercept 方法返回一个可观察对象,这意味着我们可以捕获成功和错误通道并根据需要对其进行操作。这是执行我们想要的任何日志记录的正确位置。我们还可以检查 401 Unauthorized 响应并提示用户重新登录。无论哪种方式,我们都需要设置拦截器来处理响应。

这也是缓存任何失败请求的好地方。当令牌刷新并且我们想在获取新令牌后重试请求时,这会派上用场。

通过这一点,我们可以选择在刷新用户令牌后调用 **retryFailedRequests** 来关闭之前失败的请求。这只是一个小的补充,可以帮助改善用户体验,特别是当您的令牌生命周期很短时。

总结

Angular 4.3 提供了处理 HTTP 请求的新功能集。其中最有用的一项可能是新的 **HttpInterceptor** 接口,它允许我们修改传出的请求和传入的响应。此功能极大地简化了许多以前困难的任务,并消除了自 **Angular 2** 早期以来一直存在的许多类包装器的需求。