Angular2: Resolving a cyclic dependency between Http intercepting factory and auth service

Discussão em 'Angular' iniciado por Aakash Jain, Setembro 13, 2025.

  1. Aakash Jain

    Aakash Jain Guest

    I have the following auth service:

    @Injectable()
    export class AuthService {

    //...

    constructor(private http: Http, private router: Router) {
    //...
    }

    public login(username: string, password: string): Observable<boolean> {
    // perform login
    }

    public logout() {
    // perform cleanup
    this.router.navigateByUrl('/login');
    }
    }


    And the following Http interceptor factory:

    @Injectable()
    class MyHttpInterceptor extends Http {

    constructor(backend: ConnectionBackend, defaultOptions: RequestOptions, private authService: AuthService) {
    super(backend, defaultOptions);
    }

    request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
    return this.intercept(super.request(url, options));
    }

    get(url: string, options?: RequestOptionsArgs): Observable<Response> {
    return this.intercept(super.get(url, options));
    }

    post(url: string, body: string, options?: RequestOptionsArgs): Observable<Response> {
    return this.intercept(super.post(url, body, this.getRequestOptionArgs(options)));
    }

    put(url: string, body: string, options?: RequestOptionsArgs): Observable<Response> {
    return this.intercept(super.put(url, body, this.getRequestOptionArgs(options)));
    }

    delete(url: string, options?: RequestOptionsArgs): Observable<Response> {
    return this.intercept(super.delete(url, options));
    }

    getRequestOptionArgs(options?: RequestOptionsArgs): RequestOptionsArgs {
    if (options == null) {
    options = new RequestOptions();
    }
    if (options.headers == null) {
    options.headers = new Headers();
    }
    // add headers required by our backend
    return options;
    }

    intercept(observable: Observable<Response>): Observable<Response> {
    return observable.catch((err, source) => {
    if (err.status == 401) {
    this.authService.logout();
    return Observable.empty();
    } else {
    return Observable.throw(err);
    }
    });

    }
    }

    export function myHttpInterceptorFactory(backend: ConnectionBackend, options: RequestOptions, authService: AuthService): MyHttpInterceptor {
    return new MyHttpInterceptor(backend, options, authService);
    }


    Basically the requirement here is that if any response is ever received from the backend with status 401, the logout procedure should start.

    The setup in App module is as follows:

    @NgModule({
    imports: [
    HttpModule,
    //...
    ],
    declarations: [
    AppComponent,
    //...
    ],
    providers: [
    {
    provide: Http,
    useFactory: myHttpInterceptorFactory,
    deps: [XHRBackend, RequestOptions, AuthService]
    },
    AuthService,
    //...
    ],
    bootstrap: [AppComponent]
    })
    export class AppModule {
    }


    This creates a cyclic dependency error where the Http interceptor needs AuthService, but AuthService needs Http.

    Error: Provider parse errors:
    Cannot instantiate cyclic dependency! Http: in NgModule AppModule in ./AppModule


    I tried using forwardRef to inject Http in AuthService, but that didn't change anything.

    Any help on how to restructure would be great.

    Continue reading...

Compartilhe esta Página