我想在全球范围内使用2个拦截器(httpInterceptorProviders, jwtInterceptorProviders),但在我的惰性模块中不起作用。 我有CoreModule和X延迟加载模块。奇怪的是,我有一个由swagger生成器(http服务)自动生成的代码,该调用被拦截,但是当我使用自定义http服务拦截器时却无法拦截此请求。
我在哪里获得提供商的Index.ts
/** Http interceptor providers in outside-in order */
export const httpInterceptorProviders = [
{ provide: HTTP_INTERCEPTORS, useClass: HttpErrorInterceptor, multi: true }
];
export const jwtInterceptorProviders = [
{ provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true }
];
CoreModule,我将拦截器导入提供程序
@NgModule({
imports: [
// angular
CommonModule,
HttpClientModule,
// ngrx
StoreModule.forRoot(reducers, { metaReducers }),
StoreRouterConnectingModule.forRoot(),
EffectsModule.forRoot([AuthEffects, GoogleAnalyticsEffects]),
environment.production
? []
: StoreDevtoolsModule.instrument({
name: "Angular NgRx Material Starter"
}),
// 3rd party
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
}
}),
ApiModule.forRoot(() => {
return new Configuration({
basePath: `${environment.HOST}:${environment.PORT}`,
apiKeys: { Authorization: "" }
});
})
],
declarations: [],
providers: [
LocalStorageService,
AuthGuardService,
AnimationsService,
TitleService,
// retryHttpInterceptorProviders,
{ provide: ErrorHandler, useClass: AppErrorHandler },
httpInterceptorProviders,
jwtInterceptorProviders,
{ provide: RouterStateSerializer, useClass: CustomSerializer },
{
provide: HAMMER_LOADER,
useValue: () => new Promise(() => {})
},
AnalyticsService,
LayoutService,
StateService,
PetsServiceWithUpload
],
exports: [TranslateModule]
})
export class CoreModule {
constructor(
@Optional()
@SkipSelf()
parentModule: CoreModule
) {
if (parentModule) {
throw new Error("CoreModule is already loaded. Import only in AppModule");
}
}
}
export function HttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(
http,
`${environment.i18nPrefix}/assets/i18n/`,
".json"
);
}
AppModule
@NgModule({
declarations: [AppComponent, NavigationComponent, ErrorsComponent],
imports: [
BrowserAnimationsModule,
BrowserModule,
SharedModule,
AppRoutingModule,
AuthModule,
ThemeModule.forRoot(),
CoreModule
],
bootstrap: [AppComponent]
})
export class AppModule {}
拦截器
@Injectable()
export class JwtInterceptor implements HttpInterceptor {
private isRefreshing = false;
private refreshTokenSubject: BehaviorSubject<any> = new BehaviorSubject<any>(null);
constructor(private injector: Injector,
private localstorage: LocalStorageService,
private authService: AuthService,
private store: Store<AppState>, ) { }
intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
const tokenInfo = this.localstorage.getItem(AUTH_KEY);
if (tokenInfo) {
request = this.addToken(request, tokenInfo.token);
}
console.log('TCL: JwtInterceptor -> request', request);
return next.handle(request).pipe(catchError(error => {
if (error instanceof HttpErrorResponse && error.status === 401) {
return this.handle401Error(request, next);
} else {
return throwError(error);
}
}));
}
private addToken(request: HttpRequest<any>, token: string): HttpRequest<any> {
return request.clone({
setHeaders: {
'Authorization': `Bearer ${token}`
}
});
}
private handle401Error(request: HttpRequest<any>, next: HttpHandler) {
if (!this.isRefreshing) {
this.isRefreshing = true;
this.refreshTokenSubject.next(null);
const tokenInfo = this.localstorage.getItem(AUTH_KEY);
return this.authService.authRefreshtokenPost({ refreshToken: tokenInfo.refreshToken }).pipe(
switchMap((tokenRes: any) => {
this.isRefreshing = false;
this.refreshTokenSubject.next(tokenRes.token);
this.localstorage.setItem(AUTH_KEY,
{ token: tokenRes.token, refreshToken: tokenRes.refreshToken, isAuthenticated: true });
return next.handle(this.addToken(request, tokenRes.token));
}), catchError((error) => {
console.log('TCL: JwtInterceptor -> privatehandle401Error -> error', error);
this.store.dispatch(new AuthActions.Logout({ refreshToken: tokenInfo.refreshToken }));
return next.handle(request);
}));
} else {
return this.refreshTokenSubject.pipe(
filter(token => token != null),
take(1),
switchMap(jwt => {
return next.handle(this.addToken(request, jwt));
}));
}
}
}
延迟加载模块
@NgModule({
imports: [
ThemeModule,
PetsRoutingModule,
StoreModule.forFeature("pets", petsReducer),
TranslateModule.forChild({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
},
isolate: true
}),
EffectsModule.forFeature([PetsEffects]),
InfiniteScrollModule,
SharedModule
],
declarations: [
PetsComponent,
CreatePetComponent,
ViewPetComponent,
FormPetComponent,
EditPetComponent,
PetListVirtualComponent
],
providers: []
})
export class PetsModule {}
如果我在petsModule中导出我的2个拦截器,它会拦截请求,但我只想在核心模块中将其导入一次。我签出了这个stackblitz https://stackblitz.com/edit/angular-http-interceptor-working-for-lazy-loaded-module?file=src/app/core/token-interceptor.service.ts,并确保只在我的核心模块中导入HttpClientModule。
答案 0 :(得分:0)
对于全局使用拦截器,并且提供者位于核心模块中,应添加@Injectable({ providerIn:'root' })在拦截器的顶部,例如此处 https://stackblitz.com/edit/angular-http-interceptor-working-for-lazy-loaded-module?file=src/app/core/token-interceptor.service.ts