繁体   English   中英

Angular2 Http拦截器在子模块中不起作用

[英]Angular2 Http Interceptor not working in child module

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

@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 中,它工作得很好。 直到我尝试从子模块中使用它。 来自这里的最佳答案: 在 Angular2 中继承从父模块​​到子模块的导入声称 angular2 不会让您使整个应用程序全局可用。 这是正确的吗?

我只是通过导入 RequestInterceptor 并在模块的提供程序中设置它来让它从子模块工作,但我宁愿不必这样做以使其使用起来不那么麻烦。

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

具体评论如下:

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

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

这种很糟糕 - 当另一个开发人员稍后将其导入 ChildModule 并且没有意识到拦截逻辑不再起作用时,感觉很容易导致错误。 但这似乎就是它的方式。

我遇到了类似的问题。 我得到了一个自定义 HTTP 拦截器,用于将 JWT 发送到 API 并且奇怪的是,当我的一些组件正常工作时,其中一些组件只是被服务器以 401 拒绝。经过一些试验和错误后,我阅读了@MattW 的答案并意识到有多个在我的应用程序中导入的 HttpClientModules。 我将它们全部清除并仅在 AppModule(根)中导入 HttpClientModule。 在那之后,一切都固定了。

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

直接引用 angular 文档:

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

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

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

@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 中,它工作得很好。 直到我尝试从子模块中使用它。 来自这里的最佳答案: 在 Angular2 中继承从父模块​​到子模块的导入声称 angular2 不会让您使整个应用程序全局可用。 这样对吗?

我只是通过导入 RequestInterceptor 并在模块的提供程序中设置它来让它从子模块工作,但我宁愿不必这样做以使其使用起来不那么麻烦。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM