【问题标题】:HttpInterceptor provided in Angular library is not working from Angular appAngular 库中提供的 HttpInterceptor 不适用于 Angular 应用程序
【发布时间】:2020-01-01 13:19:24
【问题描述】:

我正在开发一个 Angular 库,其中有一个提供HttpInterceptor 的身份验证模块。主要思想是让这个拦截器在任何导入此身份验证模块的应用程序中自动运行,而无需对其进行任何额外设置。

到目前为止,我有以下内容:

身份验证模块

@NgModule({
  imports: [ConcreteAuthModule],
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: BearerInterceptor,
      multi: true
    }
  ]
})
export class AuthenticationModule {
  static forRoot(config: AuthConfig): ModuleWithProviders {
    return {
      ngModule: AuthenticationModule,
      providers: [
        {
          provide: AUTH_CONFIG,
          useValue: config
        }
      ]
    };
  }
}

ConcreteAuthModule

@NgModule({
  imports: [ThirdPartyLibModule],
  providers: [
    {
      provide: AuthenticationService,
      useClass: ConcreteAuthService
    }
  ]
})
export class ConcreteAuthModule { }

承载拦截器

@Injectable()
export class BearerInterceptor implements HttpInterceptor {
  constructor(private authService: AuthenticationService) { }

  intercept(
    req: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    const headers: any = {};

    if (this.authService.isUserAuthenticated()) {
      headers.Authorization = `Bearer ${this.singleSignOnService.getUserToken()}`;
    }

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

    return next.handle(authReq);
  }
}

从一个测试 Angular 应用程序中,我在 AppModule 中通过以下方式导入此模块:

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    HttpClientModule,
    AuthenticationModule.forRoot({ /* config stuff */ })
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {}

我检查了一些第三方库是如何做到这一点的,还遇到了几个讨论这个问题的 Stack Overflow 问题,他们都建议创建一个 Angular 模块(我已经有了它:AuthenticationModule),然后提供 http -拦截器(也已经有了),最后从 Angular 应用程序中导入这个模块(也这样做了)。

但是,我的应用程序中的任何 http 请求都没有被拦截。

尝试直接从我的测试应用导入BearerInterceptor 并在 AppModule 上提供它,如下所示:

import { BearerInterceptor } from 'my-lib':

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    HttpClientModule,
    AuthenticationModule.forRoot({ /* config stuff */ })
  ],
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: BearerInterceptor,
      multi: true
    }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

这行得通!但这种解决方法不是我想要的......

【问题讨论】:

  • 你的角度版本是多少?
  • @SheikAlthaf 我的 Angular 版本是 8.1.0
  • 据我所知,拦截器依赖于 HttpClientModule,因此请求直接从 AppModule 传递,因此 AuthenticationModule 拦截器没有得到考虑。我就是这么想的,也许其他人会帮忙。仅供参考,angular.io/guide/http#http-interceptors

标签: javascript angular typescript angular-http-interceptors


【解决方案1】:

问题是因为我在本地安装库以进行如下测试:

$ npm i --save my-lib_path/dist/my-lib

在我发布它并从 npm 注册表安装它之后,它运行良好:

$ npm i --save my-lib

【讨论】:

    【解决方案2】:

    您已经非常接近可行的解决方案了。

    关键是看AppModule是如何导入模块的。

      imports: [
        BrowserModule,
        HttpClientModule,
        AuthenticationModule.forRoot({ /* config stuff */ })
      ],
    

    这就是AppModule 导入AuthenticationModule 的方式,但NgModule 不提供HTTP_INTERCEPTORS。

    您已在 @NgModule() 装饰器中提供了令牌,但您的应用程序并未使用该模块。它是forRoot() 函数定义的模块。

    将HTTP_INTERCEPTORS 的声明移至forRoot() 函数。

    试试这个:

    @NgModule({
        imports: [ConcreteAuthModule]
    })
    export class AuthenticationModule {
        static forRoot(config: AuthConfig): ModuleWithProviders {
            return {
                ngModule: AuthenticationModule,
                providers: [
                    {
                        provide: AUTH_CONFIG,
                        useValue: config
                    }, {
                        provide: HTTP_INTERCEPTORS,
                        useClass: BearerInterceptor,
                        multi: true
                    }
                ]
            };
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-15
      • 2018-06-10
      • 2021-01-19
      • 2020-01-07
      相关资源
      最近更新 更多