2017-05-15 14 views
1

カスタムhttpリクエストが期限切れになる前にトークンをリフレッシュしたい。私はそれが無限ループに入るトークンをリフレッシュする時に理解したよう角度2カスタムhttpリクエストの前にリフレッシュトークン

Token refresh is required app.js:1:92855 
updateToken() method inside app.js:1:93301 
tokenNotExpired?: false app.js:1:92674 
Token refresh is required app.js:1:92855 
updateToken() method inside app.js:1:93301 
tokenNotExpired?: false app.js:1:92674 
Token refresh is required app.js:1:92855 
updateToken() method inside app.js:1:93301 
tokenNotExpired?: false app.js:1:92674 
Token refresh is required app.js:1:92855 
updateToken() method inside app.js:1:93301 
tokenNotExpired?: false app.js:1:92674 
............ lots of the same sentences and finally exception: 

EXCEPTION: Uncaught (in promise): Error: Error in :0:0 caused by: too much recursion 
[email protected]://localhost/xxx/node_modules/zone.js/dist/zone.min.js:1:11750 
............ 

:私はトークンの有効期限が切れていることを確信しているが、それは次のコンソール結果を与えるとき、私は私のコードを試してみてください。私は、ボタンを使ってupdateToken()メソッドをどこか別の場所でテストしたところ、正常に動作しています。

私は間違っていますか?あなたはHttp.prototype.post.apply(this...)に相当することになるsuper.postを呼び出している、とsuper.postが内部this.request()を呼び出しますあなたのupdateTokenメソッド内

カスタムHTTPサービス

import { Injectable } from '@angular/core'; 
import { Http, XHRBackend, RequestOptions, Request, RequestOptionsArgs, Response, Headers } from '@angular/http'; 
import { tokenNotExpired } from "angular2-jwt"; 
import { Observable } from "rxjs/Observable"; 

@Injectable() 
export class HttpService extends Http { 

    constructor (backend: XHRBackend, options: RequestOptions) { 
     let token = localStorage.getItem('access_token'); // your custom token getter function here 
     options.headers.set('Authorization', `Bearer ${token}`); 
     super(backend, options); 
    } 

    request(url: string|Request, options?: RequestOptionsArgs): Observable<Response> { 
     let token = localStorage.getItem('access_token'); 

     if (typeof url === 'string') { // meaning we have to add the token to the options, not in url 
      if (!options) { 
       // let's make option object 
       options = {headers: new Headers()}; 
      } 
      options.headers.set('Authorization', `Bearer ${token}`); 
     } else { // we have to add the token to the url object 
      url.headers.set('Authorization', `Bearer ${token}`); 
     } 

     console.log("tokenNotExpired?: " + tokenNotExpired('access_token')); 

     if(tokenNotExpired('access_token')){ // if token is NOT expired 

      return super.request(url, options).catch(this.catchAuthError(this)); 

     }else{ // if token is expired 
      console.log("Token refresh is required"); 
      return this.updateToken() 
       .flatMap((result: boolean) => { 
        console.log("updateToken result"); 
        console.log(result); 
        if (result) { 
         return super.request(url, options).catch(this.catchAuthError(this)); 
        } else { 
         return Observable.throw(new Error('Can\'t refresh the token')); 
        } 

       }); 
     } 
    } 

    updateToken(): Observable<any> { 

     console.log("updateToken() method inside"); 

     let body: string = 'refresh_token=' + localStorage.getItem('refresh_token') + '&client_id=' + localStorage.getItem('resource') + '&grant_type=refresh_token'; 

     return super.post(
      localStorage.getItem("authUrl"), 
      body, 
      new RequestOptions({headers: new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' })}) 
     ) 
      .map((response: Response) => { 
       let returnedBody: any = response.json(); 
       console.log("post returnedBody"); 
       console.log(returnedBody); 
       if (typeof returnedBody.access_token !== 'undefined'){ 
        localStorage.setItem('access_token', returnedBody.access_token); 
        localStorage.setItem('refresh_token', returnedBody.refresh_token); 

        console.log("Token Refreshed: refreshed access_token"); 
        console.log(localStorage.getItem('access_token')); 

        return true; 
       } 
       else { 
        return false; 
       } 
      }); 
    } 

    private catchAuthError (self: HttpService) { 
     return (res: Response) => { 
      console.log(res); 
      return Observable.throw(res); 
     }; 
    } 
} 

アプリモジュール

@NgModule({ 
    imports: [ .......... ], 
    declarations: [ ....... ], 
    providers: [ 
    { 
     provide: HttpService, 
     useFactory: (backend: XHRBackend, options: RequestOptions) => { 
     return new HttpService(backend, options); 
     }, 
     deps: [XHRBackend, RequestOptions] 
    } 

    ], 
    bootstrap: [ Application ] 
}) 
+0

'updateToken()内の' super.post'は 'this.request'を内部的に呼び出します...' this'はあなたのカスタム 'HttpService'です。 – n00dl3

+0

@ n00dl3 'HttpService'を使わずに投稿を呼び出せますか? –

+0

いいえ、代わりに 'super.request'を呼び出す必要があります。 (もちろん、オーバーライドされたメソッドを呼び出さない場合)。 – n00dl3

答えて

2

thisという文脈はあなたのカスタムHttpServiceですが、それはHttpServicerequestメソッドの再帰呼び出しで終わります。代わりにsuper.requestを呼び出す必要があります:

return super.request(
    new Request({ 
     method: RequestMethod.Post, 
     url: localStorage.getItem("authUrl"), 
     body, 
     headers: new Headers({ 
     'Content-Type': 'application/x-www-form-urlencoded' 
     }) 
    }) 

) 
    .map((response: Response) => { 
    let returnedBody: any = response.json(); 
    console.log("post returnedBody"); 
    console.log(returnedBody); 
    if (typeof returnedBody.access_token !== 'undefined') { 
     localStorage.setItem('access_token', returnedBody.access_token); 
     localStorage.setItem('refresh_token', returnedBody.refresh_token); 

     console.log("Token Refreshed: refreshed access_token"); 
     console.log(localStorage.getItem('access_token')); 

     return true; 
    } else { 
     return false; 
    } 
    }); 

はまた、カスタムHTTPサービスを作成するための最高のアイデアではないかもしれないことに注意してください。

しかし、たぶん、あなたはおそらく単にajax呼び出しからいくつかの単純な静的データを取得するために認証する必要はないので、httpを注入するサービスを作成することができます。

これはまた、再帰呼び出しスタックを超過して遭遇した問題を回避します。

関連する問題