Angular库中提供的HttpInterceptor在Angular应用中无法正常工作

时间:2019-08-28 10:25:32

标签: javascript angular typescript angular-http-interceptors

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

到目前为止,我的工作是:

AuthenticationModule

@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 { }

BearerInterceptor

@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-interceptor(已经有)了,最后从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 {}

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

2 个答案:

答案 0 :(得分:1)

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

关键在于查看AppModule如何导入模块。

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

这就是AuthenticationModule导入AppModule的方式,但是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
                }
            ]
        };
    }
}

答案 1 :(得分:1)

问题是因为我出于测试目的在本地安装库,如下所示:

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

我发布它并从npm注册表中安装它后,效果很好:

$ npm i --save my-lib