In my Angular 2 project I make API calls from services that return an Observable. The calling code then subscribes to this observable. For example:
getCampai
To avoid the cyclic referencing issue that is caused by having services like "Router" being injected into an Http derived class, one must use the post-constructor Injector method. The following code is a working implementation of an Http service that redirects to Login route each time a REST API returns "Token_Expired". Note that it can be used as a substitution to the regular Http and as such, doesn't require to change anything in your application's already existing components or services.
app.module.ts
providers: [
{provide: Http, useClass: ExtendedHttpService },
AuthService,
PartService,
AuthGuard
],
extended-http.service.ts
import { Injectable, Injector } from '@angular/core';
import { Request, XHRBackend, RequestOptions, Response, Http, RequestOptionsArgs, Headers } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { Router } from '@angular/router';
import { AuthService } from './auth.service';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
@Injectable()
export class ExtendedHttpService extends Http {
private router;
private authService;
constructor( backend: XHRBackend, defaultOptions: RequestOptions, private injector: Injector) {
super(backend, defaultOptions);
}
request(url: string | Request, options?: RequestOptionsArgs): Observable {
if (typeof url === 'string') {
if (!options) {
options = { headers: new Headers() };
}
this.setHeaders(options);
} else {
this.setHeaders(url);
}
console.log("url: " + JSON.stringify(url) +", Options:" + options);
return super.request(url, options).catch(this.catchErrors());
}
private catchErrors() {
return (res: Response) => {
if (this.router == null) {
this.router = this.injector.get(Router);
}
if (res.status === 401 || res.status === 403) {
//handle authorization errors
//in this example I am navigating to login.
console.log("Error_Token_Expired: redirecting to login.");
this.router.navigate(['signin']);
}
return Observable.throw(res);
};
}
private setHeaders(objectToSetHeadersTo: Request | RequestOptionsArgs) {
if (this.authService == null) {
this.authService = this.injector.get(AuthService);
}
//add whatever header that you need to every request
//in this example I could set the header token by using authService that I've created
//objectToSetHeadersTo.headers.set('token', this.authService.getToken());
}
}