Angle 4.3 HttpClient: réponse D'interception

Dans la documentation sur le nouveau HttpClientModule inclus dans la nouvelle version Angulaire 4.3, le mécanisme d'intercepter les demandes est très bien expliqué. Il est également fait mention du mécanisme d'interception de la réponse, mais je ne trouve rien à ce sujet.

quelqu'un aurait-il une idée sur la façon d'intercepter une réponse afin de modifier le corps du message avant de l'envoyer au service?

Merci.

38
demandé sur astro8891 2017-08-08 14:19:40

4 réponses

j'ai récemment fait un HttpInterceptor afin de résoudre les références cycliques dans certains JSON du côté client, remplaçant essentiellement n'importe quel objet par un $ref propriété avec l'objet dans le JSON qui a une correspondance $id propriété. (C'est la sortie que vous obtenez si Json.Net est configuré avec PreserveReferencesHandling.Objects et ReferenceLoopHandling.Ignore).

les réponses ici m'ont aidé d'une certaine manière, mais aucune d'elles ne montre comment modifier le corps de la réponse, comme les besoins de L'OP. Pour ce faire, on a besoin de cloner l' de l'événement et de mettre à jour le corps, comme suit:

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(req).map(event => {
        if (event instanceof HttpResponse && shouldBeIntercepted(event)) {
            event = event.clone({ body: resolveReferences(event.body) })
        }         
        return event;
    });
}

tout événement qui ne devrait pas être modifié est simplement transmis au gestionnaire suivant.

22
répondu sigbjornlo 2018-06-06 17:39:15

je suppose que vous pouvez utiliser do @federico-scamuzzi suggéré, ou vous pouvez utiliser map et catch comme:

import { Injectable } from '@angular/core';
import {
  HttpErrorResponse,
  HttpEvent,
  HttpHandler,
  HttpInterceptor,
  HttpRequest,
  HttpResponse
} from '@angular/common/http';

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    console.info('req.headers =', req.headers, ';');
    return next.handle(req)
      .map((event: HttpEvent<any>) => {
        if (event instanceof HttpResponse && ~~(event.status / 100) > 3) {
          console.info('HttpResponse::event =', event, ';');
        } else console.info('event =', event, ';');
        return event;
      })
      .catch((err: any, caught) => {
        if (err instanceof HttpErrorResponse) {
          if (err.status === 403) {
            console.info('err.error =', err.error, ';');
          }
          return Observable.throw(err);
        }
      });
  }
}

EDIT: @LalitKushwah s'interrogeait sur la redirection if(!loggedIn). J'utilise Gardes De La Route, plus précisément:

import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot
       } from '@angular/router';

import { Observable } from 'rxjs/Observable';

import { AuthService } from '../../api/auth/auth.service';
import { AlertsService } from '../alerts/alerts.service';

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(private router: Router,
              private alertsService: AlertsService) {}

  canActivate(next: ActivatedRouteSnapshot,
              state: RouterStateSnapshot
              ): Observable<boolean> | Promise<boolean> | boolean {
    if (AuthService.loggedIn()) return true;

    const url: string = state.url;

    this.alertsService.add(`Auth required to view ${url}`);
    this.router
      .navigate(['/auth'], { queryParams: { redirectUrl: url } })
      .then(() => {});
    return false;
  }
}

Ensuite, je peux simplement ajouter que comme un argument de mon itinéraire:

{
  path: 'dashboard', loadChildren:'app/dashboard/dashboard.module#DashboardModule',
  canActivate: [AuthGuard]
}
36
répondu A T 2018-02-22 15:13:03

avec la version 6 angulaire ils ont adapté RxJs 6.0 à cause de cela la plupart des solutions ci-dessus ne fonctionneront pas dans cette version particulière d'angular, c'est ainsi que vous modifiez correctement le contenu D'un Observable



import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse} from '@angular/common/http';
import {Observable} from 'rxjs/internal/Observable';
import {Injectable} from '@angular/core';
import {tap} from 'rxjs/operators';

@Injectable()
export class ResponseInterceptor implements HttpInterceptor {

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

        return next.handle(req).pipe(tap((event: HttpEvent<any>) => {
            if (event instanceof HttpResponse) {
                event = event.clone({body: this.modifyBody(event.body)});
            }
            return event;
        }));

    }

    private modifyBody(body: any) {
        /*
        * write your logic to modify the body
        * */
    }
}


6
répondu imal hasaranga perera 2018-08-08 06:42:21

D'après ce que je peux comprendre (j'ai seulement fait l'interception pour request et injecter auth token) .. vous pouvez joindre un .n'() et tester si il est une reponse .. comme (comme le dit le doc):

import 'rxjs/add/operator/do';

export class TimingInterceptor implements HttpInterceptor {
  constructor(private auth: AuthService) {}

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const started = Date.now();
    return next
      .handle(req)
      .do(event => {
        if (event instanceof HttpResponse) { //<-- HERE
          const elapsed = Date.now() - started;
          console.log(event} ms.`);
        }
      });
  }

}
4
répondu federico scamuzzi 2017-10-30 12:55:35