Search code examples
angularangular-http-interceptors

Is it possible to use HTTP_INTERCEPTORS within a nested lazy module?


I have a FooModule which is nested inside the AppModule:

AppModule:

import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.model';

@NgModule({
  imports: [
    AppRoutingModule
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

FooModule:

import { NgModule } from '@angular/core';
import { AuthInterceptorService } from '../auth/auth-interceptor.service';
import { HTTP_INTERCEPTORS } from '@angular/common/http';

@NgModule({
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: AuthInterceptorService,
      multi: true
    }
  ]
})
export class FooModule {}

The FooModule is being loaded via lazy loading:

AppRoutingModule:

const appRoutes : Routes = [
    {
        path: "foos",
        loadChildren: () =>
          import("./foos/foos.module").then(m => m.FoosModule)
    }
]

@NgModule({
    imports: [RouterModule.forRoot(appRoutes, { preloadingStrategy: PreloadAllModules })],
    exports: [RouterModule]
})
export class AppRoutingModule {
}

But only when I moves the HTTP_INTERCEPTORS into the AppModule the http-s are intercepted, Is there way to make the interceptors to work from the FooModule.

I'm asking cause the interceptor doing a specific job of adding Authorization which is relevant only to the FooModule.


Solution

  • It looks like it is possible to load HTTP_INTERCEPTORS via a nested lazy loaded module, I was only missing the import of HttpClientModule inside the nested module:

    @NgModule({
      import: HttpClientModule,
      providers: [
        {
          provide: HTTP_INTERCEPTORS,
          useClass: AuthInterceptorService,
          multi: true
        }
      ]
    })
    export class FooModule {}
    

    But, because HttpClientModule is a singleton it should be defined only once, and the best place for it is inside AppModule. So I've ended up with moving the interceptors and the http client to be imported from AppModule while modifying the resolve to be conditional resolver based on the req.url:

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        if (req.url == this._config.SecretAPI) {
            //Add Authorization Header:
            const modifiedReq = req.clone({ 
                headers: new HttpHeaders().set('Authorization', this._authService.authorizationHeaderValue)
            });
            return next.handle(modifiedReq);
        }
        else {
            return next.handle(modifiedReq);
        }
    }