HttpInterceptor in Angular 4.3: Intercepting 400 error responses

落爺英雄遲暮 提交于 2019-11-27 01:08:37

问题


I would like to intercept 401 and other errors in order to react accordingly. This is my interceptor:

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

While this works well for 200 requests, it does not intercept the error respsonses

All I see in chrome's dev console is this:

zone.js:2616 GET http://localhost:8080/backend/rest/wrongurl 404 (Not Found)

Or this

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

I would like my interceptor to deal with this. What am I missing ?


回答1:


Http sends errors down the error stream of an observable so you will need to catch them with .catch (you can read more about this here).

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



回答2:


This is probably far too late for you to use, but hopefully someone else will find it useful... This is how to rewrite the above return statement to log error responses, too:

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

I'm using this same methodology to automatically send all 401 Unauthorized responses directly to our logout method (rather than checking for a 401 at each individual call to 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();
    }
  }
});

It works like an absolute charm. :)




回答3:


At the time I was trying Angular 7+.

Unfortunately above solutions did not serve the job well because .do is not directly available on HttpHandler as of RxJs 6 pipes notion; and converting Observable to Promise does not stick.

Here is clean and up-to-date approach; I pipe the catchError operator and analyze the error and finally re-throw it by using throwError. Here is final shape of interceptor;

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

Hopefully this solution will help someone in future.




回答4:


To intercept Http response error in angular 6, I make a little trick converting Observable to Promise:

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


来源:https://stackoverflow.com/questions/45367321/httpinterceptor-in-angular-4-3-intercepting-400-error-responses

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!