2017-08-15 1 views
1

Ich versuche, ein JWT Token zu aktualisieren, wenn ich eine gewisse Ausnahme bekam, wenn es eine andere Ausnahme meine Fehlerbehandler ist, sollte mit ihnen umgehen.Winkel 2 http Exception-Handler und jwt aktualisieren

Ich habe ein Stück Code, ein, wo das Token refresh arbeitet, und ein Stück Code, wo die Exception-Handler funktionieren, aber ich kann sie einfach nicht in einer Arbeits Art und Weise kombinieren.

Das Problem ist, dass ich nicht eine Ausnahme und fange sie mit meinen Fehlerbehandler in einer beobachtbaren werfen. Hier

ist der Code, wo ich meine Token mit auffrischen kann. Wenn es fehlschlägt, prüft es, ob der Fehlercode ist, wenn es das Token aktualisiert und die Anforderung erneut versucht.

export class HttpErrorService extends Http { 

    constructor(backend: XHRBackend, defaultOptions: RequestOptions) { 
    super(backend, defaultOptions); 
    } 

    request(url: string | Request, options?: RequestOptionsArgs, disableRefresh = false): Observable<Response> { 
     return super.request(url, options).catch((error: Response) => { 
     // Refresh token on token_expired exception. 
     if (!disableRefresh && error.status === 401 && error.json().error.code === 'token_expired') { 
      return this.renewToken().flatMap((response) => { 
      const res = response.json(); 
      // Replace the token in storage. 
      localStorage.setItem('__token', res.data.token); 

      // Replace request the token with the new one. 
      if (url instanceof Request) { 
       url.headers.set('Authorization', 'Bearer ' + res.data.token); 
      } else if (options) { 
       options.headers.set('Authorization', 'Bearer ' + res.data.token); 
      } 

      // To prevent a loop disable refreshing at the next request. 
      return this.request(url, options, true); 
      }); 
     } 

     // Here I want to throw the exception. 
     // I need to be able to catch it with my exception handler. 
     // throw error; doesn't work. 
     return Observable.throw(error); 
     }); 
    } 

    private getBaseUrl(): string { 
    return environment.base_uri; 
    }; 

    renewToken(): Observable<Response> { 
    const headers = new Headers(); 
    headers.append('Authorization', 'Bearer ' + localStorage.getItem('__token')) 

    return this.post(this.getBaseUrl() + '/auth/refresh', {}, {headers: headers}); 
    } 
} 

Die einzige schlechte Sache über das oben genannte ist, dass ich die Ausnahme in meinem Ausnahmebehandler nicht fangen kann.

Der folgende Code kann Ausnahmen auslösen, die von den Fehlerbehandler fangen werden kann. Aber ich habe keine Ahnung, wie ich das Token in einem Aufruf aktualisieren kann ...

export class HttpErrorService extends Http { 

    constructor(backend: XHRBackend, defaultOptions: RequestOptions) { 
    super(backend, defaultOptions); 
    } 

    request(url: string | Request, options?: RequestOptionsArgs, disableRefresh = false): Observable<Response> { 
    return Observable.create(observer => { 
     super.request(url, options).subscribe(
     res => observer.next(res), 
     err => { 
      if (!disableRefresh && err.status === 401 && err.json().error.code === 'token_expired') { 
      // I can't return this.renewToken()... 
      } 
      observer.error(err); 
      throw new HttpException(err); // this is getting catched by the ErrorHandler 
     }, 
     () => observer.complete); 
    }); 
    } 

    private getBaseUrl(): string { 
    return environment.base_uri; 
    }; 

    renewToken(): Observable<Response> { 
    const headers = new Headers(); 
    headers.append('Authorization', 'Bearer ' + localStorage.getItem('__token')) 

    return this.post(this.getBaseUrl() + '/auth/refresh', {}, {headers: headers}); 
    } 
} 

Mein Fehler-Handler ist enthält nur eine console.log().
https://angular.io/api/core/ErrorHandler

Wie kann ich das funktionieren?

+0

Kann auch den Code hinzufügen, wo Sie tatsächlich die Anforderungsfunktion und ErrorHandler aufrufen? – trungk18

+0

@ trungk18 Ich überschreibe die Http-Klasse, so dass jede HTTP-Anfrage die Anforderungsfunktion verwendet. Es ist die Standard-Http-Bibliothek. Der ErrorHandler ist nur ein 'console.log();' –

+0

Hallo Jan, kannst du versuchen "Observable.throw (error)" anstelle von "return Observable.throw (error)" auf deinen ersten Code-Block zu werfen? – trungk18

Antwort

0

Nach einigen Stunden habe ich endlich die Lösung!

export class HttpErrorService extends Http { 

    constructor(backend: XHRBackend, defaultOptions: RequestOptions) { 
    super(backend, defaultOptions); 
    } 

    request(url: string | Request, options?: RequestOptionsArgs, disableRefresh = false): Observable<Response> { 
    return Observable.create(observer => { 
     super.request(url, options).retryWhen(attempts => this.retryRequest(attempts)).catch((error: Response) => { 
     // Refresh token on token_expired exception. 
     if (!disableRefresh && error.status === 401 && error.json().error.code === 'token_expired') { 
      return this.renewToken().flatMap((response) => { 
      const res = response.json(); 
      // Replace the token in storage. 
      localStorage.setItem('__token', res.data.token); 

      // Replace request the token with the new one. 
      if (url instanceof Request) { 
       url.headers.set('Authorization', 'Bearer ' + res.data.token); 
      } else if (options) { 
       options.headers.set('Authorization', 'Bearer ' + res.data.token); 
      } 

      // To prevent a loop disable refreshing at the next request. 
      return this.request(url, options, true); 
      }); 
     } 

     throw Observable.throw(error); 
     }).subscribe(
     res => observer.next(res), 
     err => { 
      observer.error(err); 
      throw new HttpException(err); 
     } 
    ); 
    }); 
    } 

    private getBaseUrl(): string { 
    return environment.base_uri; 
    }; 

    renewToken(): Observable<Response> { 
    const headers = new Headers(); 
    headers.append('Authorization', 'Bearer ' + localStorage.getItem('__token')) 

    return this.post(this.getBaseUrl() + '/auth/refresh', {}, {headers: headers}); 
    } 

    retryRequest(attempts: any) { 
    let count = 0; 

    return attempts.flatMap(error => { 
     return ++count >= 3 ? Observable.throw(error) : Observable.timer(count * 1000); 
    }); 
    } 

}