Выполните серию HTTP-запросов, если значения равны нулю внутри Angular перехватчика / службы - PullRequest
0 голосов
/ 17 апреля 2020

Как видно из заголовка, я пытаюсь выполнить серию http-запросов для получения данных, которые мне нужно добавить в параметры моего запроса (для целей ведения журнала бэкенда).

Например, мне нужен userName, который я могу получить с помощью конечной точки Microsoft: https://graph.microsoft.com/v1.0/me, а затем, получив userPrincipalName.

Это то, что у меня есть до сих пор:

import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { apiConfig } from './app-config';
import { tap, map } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class IdentityInfoInterceptorService implements HttpInterceptor {

  userName: string;
  ipAddress: string;
  reference: string;

  constructor(private http: HttpClient) { }

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

    if (this.userName == null) {
      this.http.get(apiConfig.graphEndpoint)
      .pipe(tap(
        profile => {
          this.userName = profile?.userPrincipalName; // another issue: Property 'userPrincipalName' does not exist on type 'Object'.
        }
      ));
    }

    if (this.ipAddress == null) {
      this.http.get("http://api.ipify.org/?format=json")
      .pipe(tap(
        response => {
          this.ipAddress = response?.ip; // Property 'ip' does not exist on type 'Object'.
        }
      ))
    }

    // wait for the above to finish before appending them to the parameters of the url.
    req = req.clone({
      setParams: {
        ...req.params, userName: this.userName, ipAddress: this.ipAddress
      }
    });

    return next.handle(req);
  }
}

Я не знаю, как правильно это реализовать, тем более что я новичок в Angular.

1 Ответ

0 голосов
/ 20 апреля 2020

Я исправил свою проблему, выполнив setTimeout в конструкторе перехватчика с задержкой 0 мс, что делает вызовы, необходимые для входа в мое приложение. В противном случае я бы получил ошибку циклической зависимости. Затем я подписался на эти вызовы в перехватчике, чтобы получить значения.

Чтобы предотвратить неправильный запрос от графа Microsoft / me api, я добавил проверку, начался ли запрос с URL-адреса веб-интерфейса. Я выполняю код для добавления параметров, только если это запрос API.

Вот так выглядит мой перехватчик:

import { Injectable, Injector } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpClient, HttpBackend } from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { apiConfig } from './app-config';

@Injectable({
  providedIn: 'root'
})
export class IdentityInfoInterceptorService implements HttpInterceptor {

  msProfile: any;
  ipAddress: string;
  reference = "";

  constructor(private injector: Injector, private httpBackend: HttpBackend, private http: HttpClient) {
    setTimeout(() => {
      this.getMsProfile()
        .subscribe((profile) => {
          console.log("setting profile to " + (profile as any)?.userPrincipalName);
          this.msProfile = profile;
        });

      this.getIpAddress()
        .subscribe((ip) => {
          console.log("setting ip to " + (ip as any)?.ip);
          this.ipAddress = (ip as any)?.ip;
        });
    }, 0);
  }

  getMsProfile() {
    if (this.msProfile) {
      return of(this.msProfile);
    }
    return this.http.get(apiConfig.graphMeEndpoint);
  }

  getIpAddress() {
    if (this.ipAddress) {
      return of(this.ipAddress);
    }
    return this.http.get(apiConfig.ipEndpoint);
  }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // check needs to be there in order to get the Microsoft profile end point without getting bad request.
    if (req.url.startsWith(apiConfig.webApi)) {
      req = req.clone({
        setParams: {
          userName: this.msProfile?.userPrincipalName ?? "undefined",
          externalIpAddress: this.ipAddress ?? "undefined"
        }
      });
    }

    return next.handle(req);
  }
}

Причина, по которой существуют функции для получения профиля и IP-адреса с возвращаемым значением (), чтобы я мог подождать, пока эти значения будут «кэшированы», прежде чем я введу любой маршрутизатор-выход приложения с * ngIf в шаблоне для маршрутизатора-выхода.

Поэтому у меня есть (частично показанный) код ниже в моем файле AppComponent (точка входа в приложение):

ngOnInit() {
    this.identityInfoService.getMsProfile().subscribe(
      () => {
        this.identityInfoService.getIpAddress().subscribe(
          () => {
            this.showLoading = false;
          },
          (error) => {
            this.showLoading = false;
          }
        );
      }
    );
...