开发者社区> 互联网编程> 正文

Angular2 拦截器,使用记录

简介: 模块中添加providers @NgModule({ providers: [ HttpService, { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor,//自定义拦截器的类名 multi: true, }, ], }) 注意multi: true 选项。
+关注继续查看

模块中添加providers

@NgModule({
providers: [
    HttpService,
    {
      provide: HTTP_INTERCEPTORS,
      useClass: AuthInterceptor,//自定义拦截器的类名
      multi: true,
    },
  ],
})

注意multi: true
选项。这是必须的,因为它会告诉 Angular 这个 HTTP_INTERCEPTORS
表示的是一个数组,而不是单个的值。

事件
注意,intercept
和HttpHandler.handle
返回的可观察对象并不是Observable<HttpResponse<any>>
,而是Observable<HttpEvent<any>>
。 这是因为拦截器所工作的层级要低于 HttpClient
接口。单个请求会生成多个事件,比如表示上传和下载过程的事件。HttpResponse
类实际上本身也是一个事件,只是它的type
是HttpEventType.HttpResponseEvent

拦截器必须透传所有它不理解或不打算修改的事件。它不能过滤掉自己不准备处理的事件。很多拦截器只关心要发出的请求,而只简单的返回next
所返回的事件流,而不修改它。
**顺序
当我们在一个应用中提供了多个拦截器时,Angular 会按照你提供时的顺序应用它们(译注:即模块的providers
数组中列出的顺序)。
**不可变性
拦截器要检查和修改准备发出的请求和接收进来的响应。但是,你可能会惊奇的发现HttpRequest
HttpResponse
类在很大程度上却是不可变的。
这是有原因的:因为应用可能会重发请求,而拦截器链可能会多次处理同一个请求。如果请求是可变的,每次重试时的请求都可能和原始的请求不一样。而不可变对象可以确保拦截器每次重试时处理的都是同一个请求。
在一种情况下类型安全体系无法在写拦截器时提供保护 —— 请求体(body)。在拦截器中修改请求体本应是无效的,但类型检查系统无法发现它。
如果确实需要修改请求体,我们就得自己复制它,修改这个复本,然后使用clone()
来复制这个请求,并使用这个新的请求体。
由于请求都是不可变的,所以不能直接修改它们。要想修改,就使用clone()
函数

创建拦截器

注意implements HttpInterceptor

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

/**什么也不做,只是简单的转发请求而不做任何修改*/
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(req);
  }
}
//替换url
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
  // This is a duplicate. It is exactly the same as the original.
  const dupReq = req.clone();

  // Change the URL and replace 'http://' with 'https://'
  const secureReq = req.clone({url: req.url.replace('http://', 'https://')});
}
import {Injectable} from '@angular/core';
import {HttpEvent, HttpInterceptor, HttpHandler, HttpRequest} from '@angular/common/http';
 
/** 设置新的头,比如替换token*/
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  constructor(private auth: AuthService) {}
 
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // Get the auth header from the service.
    const authHeader = this.auth.getAuthorizationHeader();
    // Clone the request to add the new header.
    const authReq = req.clone({headers: req.headers.set('Authorization', authHeader)});
    // Pass on the cloned request instead of the original request.
    return next.handle(authReq);
  }
}

这种克隆一个请求并设置一组新的请求头的操作非常常见,因此有了一种快捷写法:

const authReq = req.clone({setHeaders: {Authorization: authHeader}});

如果需要注入service 使用如下方式

constructor(private injector: Injector) { }
this.httpService = this.injector.get(HttpService); // get HttpService within intercept

import {Injectable, Injector} from '@angular/core';
import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
import {HttpService} from "./http-service.service";
import {Observable} from "rxjs/Observable";

/**
 * @description 拦截器,拦截所有http请求
 *  目前实现功能:
 *    1.请求的header中增加token
 */
@Injectable()
export class AuthInterceptor implements HttpInterceptor {

  private httpService: HttpService;

  constructor(private injector: Injector) {
  }

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    this.httpService = this.injector.get(HttpService); // get HttpService  within intercept

    const authReq = request.clone({headers: request.headers.set('token', localStorage.getItem("token"))});
    // Pass on the cloned request instead of the original request.
    return next.handle(authReq);
  }
}

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
+关注
互联网编程
讲个笑话,我有50年的Java编程经验,哈哈哈
文章
问答
视频
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载