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.