I want to use 2 interceptor globally (httpInterceptorProviders, jwtInterceptorProviders) but it not working in my lazy modules. I have CoreModule and X lazy load modules. The weird part is that I have an autogenerated code by swagger generator(http services) this calls being intercepted but when I use custom http services interceptor not intercept this requests.
Index.ts where I get the providers
/** 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, I import my interceptors in providers
@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 {}
Interceptor
@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));
}));
}
}
}
Lazy load module
@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 {}
If I export my 2 interceptors in petsModule its intercept the request but I want to import it once only in core module. I checkout this stackblitz https://stackblitz.com/edit/angular-http-interceptor-working-for-lazy-loaded-module?file=src/app/core/token-interceptor.service.ts and I ensure that I only import HttpClientModule in my core module.
For use interceptor globally and the providers are in core module should add @Injectable({ providedIn: 'root' }) in the top of interceptors like here https://stackblitz.com/edit/angular-http-interceptor-working-for-lazy-loaded-module?file=src/app/core/token-interceptor.service.ts