web-dev-qa-db-fra.com

HttpInterceptor in Angular 4.3: Interception de 400 réponses d'erreur

Je voudrais que intercepte 401 et d'autres erreurs afin de réagir en conséquence. Ceci est mon intercepteur:

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

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/do';

@Injectable()
export class TwsHttpInterceptor implements HttpInterceptor {

    constructor(private logger: LoggingService) { }

    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        this.logger.logDebug(request);    
        return next.handle(request)
            .do(event => {
                if (event instanceof HttpResponse) {
                    this.logger.logDebug(event);
                }
            });
    }
}

Bien que cela fonctionne bien pour 200 demandes, il n'intercepte pas les réponses d'erreur

Tout ce que je vois dans la console de développement de chrome est la suivante:

zone.js: 2616 GET http: // localhost: 8080/backend/rest/wrongurl 404 (Non Trouvé)

Ou ca

zone.js: 2616 GET http: // localhost: 8080/backend/rest/url 401 (Non autorisé)

Je voudrais que mon intercepteur traite de cela. Qu'est-ce que je rate ?

15
Tim

Http envoie des erreurs dans le flux d'erreur d'une observable, vous devrez donc les attraper avec .catch (vous pouvez en savoir plus à ce sujet ici ).

return next.handle(request)
  .do(event => {
    if (event instanceof HttpResponse) {
      this.logger.logDebug(event);
    }
  })
  .catch(err => { 
    console.log('Caught error', err);
    return Observable.throw(err);
  });
29
0mpurdy

C’est probablement trop tard pour vous, mais une autre personne trouvera cela utile. Voici comment réécrire la déclaration ci-dessus pour consigner les réponses aux erreurs:

return next.handle(request).do((event: HttpEvent<any>) => {
  if (event instanceof HttpResponse) {
    this.logger.logDebug(event);
  }
}, (error: any) => {
  if (error instanceof HttpErrorResponse) {
    this.logger.logDebug(error);
  }
});

J'utilise cette même méthode pour envoyer automatiquement toutes les réponses 401 non autorisées directement à notre méthode de déconnexion (plutôt que de rechercher un 401 à chaque appel individuel vers http):

return next.handle(request).do((event: HttpEvent<any>) => {
  if (event instanceof HttpResponse) {
    // process successful responses here
  }
}, (error: any) => {
  if (error instanceof HttpErrorResponse) {
    if (error.status === 401) {
      authService.logout();
    }
  }
});

Cela fonctionne comme un charme absolu. :)

7
Enrika

A l'époque, j'essayais Angular 7+.

Malheureusement les solutions ci-dessus n'ont pas bien servi le travail car .do n'est pas directement disponible sur HttpHandler à partir de la notion de RxJs 6 pipes; et la conversion de Observable to Promise ne colle pas. 

Voici une approche propre et à jour; Je pipe l'opérateur catchError et analyser l'erreur et enfin le relancer à l'aide de throwError. Voici la forme finale de l'intercepteur;

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(req).pipe(
      catchError((error: HttpErrorResponse) => {
        if (error.error instanceof ErrorEvent) {
          // client-side error or network error

        } else {
          // TODO: Clean up following by introducing method
          if (error.status === 498) { 
            // TODO: Destroy local session; redirect to /login
          }
          if (error.status === 401) { 
            // TODO: Permission denied; show toast
          }
        }
        return throwError(error);
      })
    );
  }

Espérons que cette solution aidera quelqu'un à l'avenir.

1
mumair

Pour intercepter l'erreur de réponse HTTP dans l'angle 6, je fais un petit tour en convertissant Observable en Promesse:

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
   const obs = next.handle(req);

   if (!window.navigator.onLine) {
     // Handle offline error
     this.messageService.showError('No Internet Connection');
     return;
   }

   obs.toPromise().catch((error) => {
     this.messageService.progress(false);
     this.messageService.showError(error.message);
   });
   return obs;
}
0
Ângelo Polotto