How to add HttpClient Interceptors conditionally in Angular

Rahul Singh picture Rahul Singh · Aug 20, 2017 · Viewed 8.2k times · Source

Recently I have been using Interceptors with Angular HttpClient.

I add headers corresponding to some HTTP GET methods and for some I do not need those headers.

How can I tell my interceptor to conditionally add interceptors to only those methods? I can even split up services like one service for headers and one without headers or one for different headers and one for different.

NgModule providers

{
  provide: HTTP_INTERCEPTORS,
  useClass: AuthInterceptor,
  multi: true,
},{
  provide: HTTP_INTERCEPTORS,
  useClass: AngularInterceptor,
  multi: true,
}

MyInterceptors

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const authReq = req.clone({headers: req.headers.set('X-Auth-Token', "-------------------------")});
    return next.handle(authReq);

  }
}


@Injectable()
export class AngularInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(req).do(event => {}, err => {
        if(err instanceof HttpErrorResponse){
            console.log("Error Caught By Interceptor");
            //Observable.throw(err);
        }
    });
  }
}

Answer

Johannes Rudolph picture Johannes Rudolph · Sep 28, 2017

Note: I haven't tried this approach myself yet but have played with the idea because we are looking at a similar problem.

If we had very simple requirements, it would be trivial to add logic in a general purpose interceptor and just decide based on URL/Method which kind of interception to perform. However, our angular app needs to call a variety of 1st party micro-services and 3rd party APIs with different requirements for interceptors. This is effectively a superset of your requirements.

One idea to implement this is to extend HttpClient for each API/Service that we need to call and set up a custom injection token for the interceptor chain. You can see how angular registers the default HttpClient here:

 providers: [
    HttpClient,
    // HttpHandler is the backend + interceptors and is constructed
    // using the interceptingHandler factory function.
    {
      provide: HttpHandler,
      useFactory: interceptingHandler,
      deps: [HttpBackend, [new Optional(), new Inject(HTTP_INTERCEPTORS)]],
    },

The interceptingHandler function is even exported as ɵinterceptingHandler. I agree this looks a little weird, not sure why it has that export name.

Anyawy, to use a custom HttpClients you can probably:

export const MY_HTTP_INTERCEPTORS = new InjectionToken<HttpInterceptor[]>('MY_HTTP_INTERCEPTORS');

...
 providers: [
    MyHttpClient,
    {
      provide: MyHttpHandler,
      useFactory: interceptingHandler,
      deps: [HttpBackend, [new Optional(), new Inject(MY_HTTP_INTERCEPTORS)]],
    },

And make sure that MyHttpClient requires a MyHttpHandler in its constructor.