Angular2 Http Interceptor在子模块中不起作用

时间:2018-02-12 22:45:54

标签: angular angular-http-interceptors

所以我创建了一个angular2模块来处理HTTP Intercepting,使用基本的拦截器,如:

@Injectable()
export class RequestInterceptor implements HttpInterceptor {
  constructor(private injector: Injector) {}

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const authService = this.injector.get(AuthService);
    if(authService.isAuthenticated()){
      const authReq = request.clone({
        setHeaders: {
          Authorization: `Bearer ${authService.getAccessToken()}`
        }
      });
      let handle = next.handle(authReq).do(event => {
        if(event instanceof HttpResponse){
          if(event.headers.has('Authorization')){
            authService.updateToken(event.headers.get('Authorization').split(' ')[1]);
          }
        }
      });
      return handle;
    }else{
      return next.handle(request);
    }
  }
}

这将为http请求添加授权标头,并在从服务器发送新标头时更新自己的标头。它的导入和提供通常如下:

{
  provide: HTTP_INTERCEPTORS,
  useClass: RequestInterceptor,
  multi: true
},

因此auth angular2模块被编译并导入到我的app.module.t中,效果很好。直到我尝试从子模块使用它。最佳答案来自:Inherit imports from parent module to child module in Angular2声称angular2不会让你在整个应用程序中全局可用。它是否正确?

我通过导入RequestInterceptor从子模块开始工作,并在模块的提供程序中进行设置,但我不必这样做,以减少使用它的麻烦。

4 个答案:

答案 0 :(得分:6)

不是最佳答案 - 但请查看此错误:https://github.com/angular/angular/issues/20575

特别是评论:

  

您应该只导入一次HttpClientModule,请参阅docs

我想你正在模块树的某个地方重新导入HttpClientModule - 可能在另一个子模块中。如果您只是在AppModule(或者如果它是导入的那个)中声明它一次,那么它应该在任何地方开始工作。无论如何,那是我的经历。

这种恶臭 - 当另一个开发人员稍后在ChildModule中导入错误时,感觉已经成熟,导致错误,并且没有意识到拦截逻辑不再起作用。但这似乎是它的方式。

答案 1 :(得分:0)

我遇到了类似的问题。我有一个自定义的HTTP拦截器,目的是将JWT发送到API,并且奇怪的是,在我的某些组件正常工作时,其中一些组件只是被401服务器拒绝了。在我的应用程序中导入了HttpClientModules。我清除了所有内容,仅在AppModule(根)中导入了HttpClientModule。之后,一切都固定了。

答案 2 :(得分:0)

我有同样的问题。拦截器未添加在延迟加载的模块中发出的令牌请求。除非您要覆盖HttpClientModule实例,否则导入HttpClientModule并不是最佳选择。如果再次导入HttpClientModule,它将覆盖根模块中声明的所有拦截器。

角度文档的直接报价:

要在整个应用程序中使用相同的HttpInterceptors实例,请仅在AppModule中导入HttpClientModule,然后将拦截器添加到根应用程序注入器中。如果跨不同模块(例如,在延迟加载模块中)多次导入HttpClientModule,则每次导入都会创建HttpClientModule的新副本,该副本将覆盖根模块中提供的拦截器。

https://angular.io/api/common/http/HttpInterceptor#usage-notes

答案 3 :(得分:-2)

解决方案是也在子模块中导入 HttpClientModule

imports: [
  ...
  HttpClientModule 
],
declarations: [...],
providers: [
 { provide: HTTP_INTERCEPTORS, useClass: RequestInterceptor, multi: true }
]