Angular 库中提供的 HttpInterceptor 无法在 Angular 应用中运行
HttpInterceptor provided in Angular library is not working from Angular app
我正在开发一个 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 拦截器(也已经有了),最后从 Angular 应用程序导入这个模块(也这样做了)。
但是,我的应用程序中 none 的 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 {}
这很有效!但是这个解决方法不是我想要的...
您非常接近可行的解决方案。
关键是看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
}
]
};
}
}
问题是因为我在本地安装库以进行如下测试:
$ npm i --save my-lib_path/dist/my-lib
在我发布它并从 npm 注册表安装它之后它工作正常:
$ npm i --save my-lib
我正在开发一个 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 拦截器(也已经有了),最后从 Angular 应用程序导入这个模块(也这样做了)。
但是,我的应用程序中 none 的 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 {}
这很有效!但是这个解决方法不是我想要的...
您非常接近可行的解决方案。
关键是看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
}
]
};
}
}
问题是因为我在本地安装库以进行如下测试:
$ npm i --save my-lib_path/dist/my-lib
在我发布它并从 npm 注册表安装它之后它工作正常:
$ npm i --save my-lib