Angular 4.3 HttpClient: Respuesta de intercepción


En la documentación sobre el nuevo HttpClientModule incluido en la nueva versión de Angular 4.3, se explica muy bien el mecanismo para interceptar solicitudes. También se menciona el mecanismo interceptor de respuesta, sin embargo, no puedo encontrar nada al respecto.

¿Alguien tiene una idea sobre cómo interceptar una respuesta para modificar el cuerpo del mensaje antes de que se envíe al servicio?

Gracias.

Author: astro8891, 2017-08-08

4 answers

Recientemente hice un HttpInterceptor para resolver referencias cíclicas en algunos JSON en el lado del cliente, esencialmente reemplazando cualquier objeto con una propiedad $ref con el objeto en el JSON que tiene una propiedad $id coincidente. (Esta es la salida que obtienes si Json.Net está configurado con PreserveReferencesHandling.Objects y ReferenceLoopHandling.Ignore).

Las respuestas aquí me ayudaron de alguna manera, pero ninguna de ellas muestra cómo modificar el cuerpo de la respuesta, como las necesidades de OP. Para hacerlo, uno necesita clonar el evento y actualizar el cuerpo, así:

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;
    });
}

Cualquier evento que no deba modificarse simplemente se pasa al siguiente controlador.

 22
Author: sigbjornlo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-06 17:39:15

Supongo que puedes usar do como sugirió @ federico-scamuzzi, o puedes usar map y catch así:

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);
        }
      });
  }
}

EDITAR: @LalitKushwah estaba preguntando acerca de redireccionar if(!loggedIn). Uso Guardias de ruta , específicamente:

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;
  }
}

Entonces simplemente puedo agregar eso como un argumento a mi ruta:

{
  path: 'dashboard', loadChildren:'app/dashboard/dashboard.module#DashboardModule',
  canActivate: [AuthGuard]
}
 36
Author: A T,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-22 15:13:03

Con la versión Angular 6 han adaptado RxJS 6.0 debido a que la mayoría de las soluciones anteriores no funcionarán en esta versión particular de angular, así es como se modifica correctamente el contenido de 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
Author: imal hasaranga perera,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-08 06:42:21

Por lo que puedo entender (solo he hecho la intercepción para solicitar e inyectar token de autenticación) .. puede adjuntar un .do () y probar si es una respuesta .. como (como dice 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
Author: federico scamuzzi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-30 12:55:35