Solvedangular Cyclic dependency error with HttpInterceptor

I'm submitting a...

[ ] Regression (a behavior that used to work and stopped working in a new release)
[x] Bug report  
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Current behavior

Trying to do the same example of AuthInterceptor like in official doc, to add a Authorization header on all requests.

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  constructor(private auth: AuthService) {}
 
  intercept(req: HttpRequest<any>, next: HttpHandler) {
    const authHeader = this.auth.getAuthorizationHeader();
    const authReq = req.clone({headers: req.headers.set('Authorization', authHeader)});
    return next.handle(authReq);
  }
}

Problem : with real code, the AuthService needs to request the server on login, signin, etc., so it itself inject HttpClient.

@Injectable()
export class AuthService {

  constructor(private http: HttpClient) {}

}

It creates this fatal error in console :

Uncaught Error: Provider parse errors:
Cannot instantiate cyclic dependency! InjectionToken_HTTP_INTERCEPTORS ("[ERROR ->]"): in NgModule AppModule in ./AppModule@-1:-1

Expected behavior

Should work, as it's a very common case. Otherwise interceptors are limited to use services without Http.

Environment

Angular version: 4.3.0
52 Answers

✔️Accepted Answer

I resolved simply not setting authService in constructor but getting in the intercept function.

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // Get the auth header from the service.
    const auth = this.inj.get(AuthenticationService);
    const authToken = auth.getAuthorizationToken();
    ...
   }

Other Answers:

My code is very similar to @cyrilletuzi, I tried @Toxicable solution, I have no more cyclic dependency but I get:

ERROR Error: Uncaught (in promise): RangeError: Maximum call stack size exceeded
RangeError: Maximum call stack size exceeded
    at _createProviderInstance$1 (core.es5.js:9480)
    ...   

@tytskyi I tried that and didn't work

  constructor(inj: Injector) {
    this.auth = inj.get(AuthService)
  }

works though

https://plnkr.co/edit/8CpyAUSJcCiRqdZmuvt9?p=preview

@will-copperleaf Which example have you tried?

You should be able to do this for example:

import { Injectable, Injector } from '@angular/core';
import { HttpInterceptor, HttpEvent, HttpRequest, HttpHandler } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { AuthService } from '../shared/auth.service';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

  private authService: AuthService;

  constructor(
    private injector: Injector
  ) { }

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

    this.authService = this.injector.get(AuthService); // get it here within intercept

    const authRequest = request.clone({
      headers: request.headers.set('Authorization', this.authService.getHeaders())
    });

    return next.handle(authRequest);
  }

}

You may also try a little hack to instatiate the service, like:

constructor(private injector: Injector) {
  setTimeout(() => {
    this.authService = this.injector.get(AuthService);
  })
}

This way you won't get the max call stack exceeded error.

More Issues: