Angular HttpClient изменить ответ в сервисе, если обнаружена ошибка - PullRequest
0 голосов
/ 14 февраля 2019

У меня есть служба, которая отправляет запросы на отдых моим веб-службам, и я хочу, чтобы, если я уловил ошибку аутентификации, я попытался снова войти в систему с помощью маркера обновления, а затем перезапустил исходный запрос и вернулновый результат.

У меня есть, например, функция get:

protected get<T>(path: string, params: any, mapper: Function): Observable<T> {
  const httpParams: HttpParams = new HttpParams({ fromObject: params});
  let urlParams = httpParams.toString();
  if (urlParams) {
    urlParams = urlParams.replace(/%5B%5D/g, '[]');
  }

  let get =  this._http.get<T>((path.indexOf('data') === 0 ? '' : this._webservicesUrl)
  + this.mapParameters(path, params) + '?' + urlParams, {
    headers: this.headers,
    responseType: 'json',
    withCredentials: true,
    observe: 'response'
  });

  return get.pipe(
    tap((res) => console.log('HTTP GET - ' + path)),
    map((response: HttpResponse<T>) => mapper(response.body)),
    catchError(this.authError(path, params, mapper)),
  );
}

На данный момент я не набрал this.authError (он пуст, потому что я не знаю, как поступить).

Мне просто нужно указать, что нужно сделать для передачи моего authError, и если это ошибка аутентификации (код 401 для меня), тогда ответ на карте должен быть изменен новым ответом на запрос.

Я также пытался с перехватчиком, но я не могу изменить ответ, просто запросите новую аутентификацию и перезапустите запрос.

- РЕДАКТИРОВАТЬ -

Я думаю, что есть какое-то отношение к перехватчикам, я запускаю что-то, что все еще не работает, но это хорошая отправная точка.

Вот перехватчик, который я создал:

import { Injectable } from '@angular/core';
import { HttpEvent, HttpHandler, HttpRequest, HttpClient, HttpInterceptor } from '@angular/common/http';
import { Observable, throwError } from 'rxjs/index';
import { catchError, switchMap } from "rxjs/internal/operators";
import { AuthenticationService } from "../services/rest/authentication.service";
import { AppStateService } from "../services/app-state.service";

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

  constructor(public http: HttpClient, public auth: AuthenticationService, private appState: AppStateService) {
  }

  public intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    console.log('===== Intercept =====');
    console.log(req);
    return next.handle(req).pipe(
      catchError(err => {
        console.log(err);

        this.refreshToken().subscribe( resolve => {
          console.log('RESOLVE');
          // clone the original request
           if (resolve) {
              console.log('REQ REPEAT');
              const authReqRepeat = req.clone({
                 headers: req.headers.set('Authorization', 'Bearer' + this.appState.token)
              });

              // resend the request
              return next.handle(authReqRepeat);
           }

        }, error => {
          console.log('ERROR');
          return throwError(error);
        });
      })
    );
  }

  public refreshToken(): Observable<boolean> {
    const obs: Observable<boolean> = new Observable<boolean>(observer => {
      this.auth.loginWithEmail(this.appState.userMail, null, 'refresh_token', this.appState.refreshToken).subscribe(
        resolve => {
          console.log('RELOG OK');
          console.log(this.appState);
          observer.next(true);
          observer.complete();
        }, error => {
          console.log('RELOG NOT OK');
          observer.next(false);
          observer.complete();
        }
      );
    });

    return obs;
  }

}

Кажется,работает отлично, хожуt весь мой console.log, но когда дело доходит до return next.handle(authReqRepeat);, запрос не отправляется, поэтому приложение все еще ожидает ответа, который никогда не будет получен.

...