2017-05-15 2 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 서비스 Http.prototype.post.apply(this...)에 해당 될 것이며, super.post 내부 this.request()를 호출하여 updateToken 방법 내부

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

    ], 
    bootstrap: [ Application ] 
}) 
+0

'()''this.request' 내부적으로 ...'this'있는 사용자 정의'HttpService'를 호출합니다. – n00dl3

+0

@ n00dl3'HttpService'를 사용하지 않고 게시물에 전화 할 수 있습니까? –

+0

아니요, 대신 super.request를 호출해야합니다. (만약 오버라이드 된 메소드를 호출하지 않는다면). – n00dl3

답변

2

당신이 super.post을 요구하고있다

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); 
     }; 
    } 
} 

응용 프로그램 모듈.

컨텍스트가 사용자 지정 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를 주입하는 서비스를 만들 수 있습니다.

이렇게하면 재귀 호출 스택이 초과되어 발생하는 문제를 피할 수 있습니다. updateToken`내부 super.post`

@Injectable() 
export class MyAuhtHttpService{ 

    constructor(private http:Http){} 

}