角度-多个错误拦截器

时间:2018-08-01 09:56:18

标签: angular typescript angular-httpclient angular-http-interceptors

我有一个拦截器,可以处理错误并对错误做出反应。如果有错误,它将执行Observable.throw(err)

现在,我需要一个拦截器,该拦截器捕获401状态,然后获取存储的刷新令牌并创建新的访问令牌,在authorization上设置req标头,然后再次尝试失败的请求带有新标题。

这是第一个错误拦截器,请注意Observable.throw(err)部分:

@Injectable()

export class ErrorInterceptor implements HttpInterceptor {

  constructor(
    private config: Config
  ) {}

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

    return next.handle(req)
      .pipe(
        catchError((err) => {

          if (err instanceof HttpErrorResponse) {

            if (err.status === 401) {
              this.config.onUnauthorized(err);
            }
            else {
              this.config.onHttpError(err);
            }
          }

          return Observable.throw(err);
        }
      )
    );
  }
}

这是第二个拦截器:

@Injectable()

export class TokenInterceptor implements HttpInterceptor {

  constructor(private api: Api, private cs: ClientStorage, private router: Router) { }

  private getNewAccessToken(req: HttpRequest<any>, next: HttpHandler) {
    console.log(0);
    return this.api.post<any>('token', null, {
      grant_type: 'refresh_token',
      refresh_token: this.cs.getItem(AppConstants.appState).refreshToken,
      scope: 'user'
    });
  }

  private appendAccessToken(req, token) {
    console.log(1, token)
    return req.clone({
      setHeaders: {
        authorization: `Bearer ${token}`
      }
    });
  }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

    const appState = this.cs.getItem(AppConstants.appState);
    const accessToken = appState ? appState.accessToken : null;

    return next.handle(this.appendAccessToken(req, accessToken))
      .pipe(
        catchError((error: any) => {
          console.log(error);
          if (error instanceof HttpErrorResponse) {

            if (error.status === 401) {

              console.log('Unauthorized');

              return this.getNewAccessToken(req, next)
                .pipe(
                  mergeMap((res) => {

                  this.cs.setItem(AppConstants.appState, {...appState, accessToken: res.access_token});

                  return next.handle(this.appendAccessToken(req, res.access_token));
                })
              );
            }
            else if (error.status === 403) {
              this.router.navigate(['/login']);
            }
          }
          else {
            console.log(3)
            return Observable.throw(error);
          }
        })
      );
  }
};

这里的问题是我添加的拦截器似乎没有执行任何操作,它初始化并拦截了不是错误但catchError位没有的http请求”如果有错误,则运行。 catchError中的ErrorInterceptor运行正常,因此我相信它们会相互干扰。

如何使令牌拦截器按预期工作?

1 个答案:

答案 0 :(得分:0)

我试图实现类似的情况。它按预期工作。这是StackBlitz Demo

这样,我看不到您的代码有任何问题,但是我想知道为什么您将“ req”和“ next”传递给了 getNewAccessToken()方法。在该方法中未使用它们。

相关问题