Reputation: 87
I've created custom Http service to override "request" method which updates token on each request if it's required. But problem is that I'm receiving "Cyclic dependency" error. Any idea how to fix?
Custom Http service:
import { Injectable } from '@angular/core';
import {
Request, XHRBackend, RequestOptions, Response, Http, RequestOptionsArgs, Headers } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
import {UserService} from "../services/user.service";
@Injectable()
export class VodHttpService extends Http {
constructor(backend: XHRBackend, defaultOptions: RequestOptions, private userService : UserService ) {
super(backend, defaultOptions);
}
request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
//adding access token to each http request before calling super(..,..)
let token = this.userService.token;
if (typeof url === 'string') {
if (!options) {
options = { headers: new Headers() };
}
if ( url != this.userService.PUBLIC_TOKEN_URL ) {
options.headers.set('Authorization', `Bearer ${token}`);
}
}
else {
if ( url.url != this.userService.PUBLIC_TOKEN_URL ) {
url.headers.set('Authorization', `Bearer ${token}`);
}
}
console.log(url);
return super.request(url, options)
.catch((error) => {
//if got authorization error - try to update access token
if (error.status = 401) {
return this.userService.updateToken()
.flatMap((result: boolean) => {
//if got new access token - retry request
if (result) {
return this.request(url, options);
}
//otherwise - throw error
else {
return Observable.throw(new Error('Can\'t refresh the token'));
}
})
}
else {
Observable.throw(error);
}
})
}
}
My singleton user service is looking like:
import {Component, Injectable, Injector} from '@angular/core';
import {Http} from "@angular/http";
import {Observable} from "rxjs";
import {environment} from "../../environments/environment";
@Injectable()
export class UserService {
public token : string;
public PUBLIC_TOKEN_URL = environment.token_url;
constructor (private _http: Http) { }
updateToken() : Observable<boolean> {
let url = this.PUBLIC_TOKEN_URL;
return this._http.get(url).map( res => {
// return res.json();
if (typeof res.json().access_token !== 'undefined'){
this.token = res.json().access_token;
return true;
} else {
return false;
}
});
}
}
I know where is way to fix it by using Injector but I think it's ugly method.
Upvotes: 1
Views: 246
Reputation: 3671
The provider definition for your custom VodHttpService is not correct. It should be something like this:
export function vodHttpFactory(backend: XHRBackend, options: RequestOptions, userService: UserService) {
return new VodHttpService(backend, options, userService);
}
@NgModule({
// other stuff
providers: [
UserService,
{
provide: VodHttpService,
useFactory: vodHttpFactory,
deps: [XHRBackend, RequestOptions, UserService]
}
]
})
Note that the vodHttpFactory
function is written like that to be compatible with AOT, in case you need it.
Upvotes: 1