Angular перехватчик, обработать ошибку HTTP и повторить попытку - PullRequest
1 голос
/ 11 апреля 2020

У меня есть базовая c система JWT и перехватчик, который проверяет, не выполнен ли запрос из-за несанкционированного доступа.

import {Injectable} from '@angular/core';
import {HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
import {Observable, throwError} from 'rxjs';
import {AuthService} from '../services/auth.service';
import {catchError, retryWhen} from 'rxjs/operators';

@Injectable()
export class AuthenticationErrorInterceptor implements HttpInterceptor {

  private readonly _authService: AuthService;

  constructor(authService: AuthService) {
    this._authService = authService;
  }

  public intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const authReq = req.clone({headers: req.headers});
    return next.handle(authReq)
      .pipe(
        catchError((err) => this._handleAuthError(err)),
        retry(3)
      );
  }

  private _handleAuthError(error: HttpErrorResponse): Observable<any> {
    if (error.status === 401 || error.status === 403) {
      return this._authService.authenticate();
    }

    return throwError(error);
  }
}

Если запрос не выполняется, я хочу отправить запрос повторно после того, как позвонил this._authService.authenticate();. Он будет повторно аутентифицироваться, потому что обработка ошибок вынуждает его повторно аутентифицировать, но затем он не вызывает запрос, вызывающий сбой приложения, пока я не обновлю sh браузер.

Как мне заставить моего охранника повторить запрос?

Я тоже пытался использовать retryWhen, но получаю такой же / похожий результат.

1 Ответ

1 голос
/ 11 апреля 2020

Вызвать .next в обработчике HTTP после повторной аутентификации сеанса. В идеале вы должны вернуть токен аутентификации из вашего метода authenticate, который затем может быть добавлен в заголовки авторизации запроса.

import {Injectable} from '@angular/core';
import {HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
import {Observable, throwError} from 'rxjs';
import {AuthService} from '../services/auth.service';
import {catchError, retryWhen} from 'rxjs/operators';

@Injectable()
export class AuthenticationErrorInterceptor implements HttpInterceptor {

  private readonly _authService: AuthService;

  constructor(authService: AuthService) {
    this._authService = authService;
  }

  public intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
      return next.handle(req)
            .pipe(
                catchError((error: HttpErrorResponse) => {
                  if (error.status === 401 || error.status === 403) {
                    return this._authService.authenticate()
                      .pipe(
                        mergeMap((token) => next.handle(req.clone({
                                    headers: req.headers.set(AUTH_TOKEN_NAME_HERE, token)
                                })))
                      );
                  }

                    return throwError(error);
                })
            );
  }
}
...