Dans la documentation sur la nouvelle HttpClientModule
incluse dans la nouvelle version de Angular 4.3, le mécanisme d’interception des requêtes 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 at-il une idée de la façon d'intercepter une réponse afin de modifier le corps du message avant qu'il ne soit envoyé au service?
Merci.
J'ai récemment créé un HttpInterceptor
afin de résoudre les références cycliques dans certains JSON côté client, en remplaçant essentiellement tout objet par une propriété $ref
par l'objet du JSON correspondant à $id
. propriété. (Il s’agit du résultat obtenu si Json.Net est configuré avec PreserveReferencesHandling.Objects
et ReferenceLoopHandling.Ignore
).
Les réponses fournies ici m'ont aidé dans une certaine mesure, mais aucune d'elles n'a montré comment modifier le corps de la réponse, à l'instar des besoins du PO. Pour ce faire, il faut cloner l'événement et 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.
Je suppose que vous pouvez utiliser do
comme suggéré par @ federico-scamuzzi, ou vous pouvez utiliser map
et catch
comme suit:
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 demandait de rediriger if(!loggedIn)
. J'utilise Route Guards , 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 cela comme argument à mon itinéraire:
{
path: 'dashboard', loadChildren:'app/dashboard/dashboard.module#DashboardModule',
canActivate: [AuthGuard]
}
Avec la version Angular 6, ils ont adapté RxJs 6.0 en raison de ce que la plupart des solutions ci-dessus ne fonctionneront pas dans cette version particulière de 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
* */
}
}
D'après ce que je peux comprendre (je n'ai fait que l'interception à la demande et l'injection d'auth token) .. vous pouvez attacher un .do () et tester si est une réponse .. like (comme le dit la 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.`);
}
});
}
}