Search code examples
angularangular-http-interceptors

Angular Interceptor route to a different path based on response


I'm playing around with Angular interceptor and i wanted to re route if the response status is 401 and below is what i've tried .

@Injectable()
export class AuthInterceptorService implements HttpInterceptor {

  constructor(private _localStorageService: LocalStorageService, private _router: Router, private _location: Location) { }


  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if (req.url.includes("/login")) {
      return next.handle(req);
    }
    let authToken: LocalStorage = this._localStorageService.getItem('auth-token');
    if (authToken) {
      return next.handle(
        req.clone({
          headers: req.headers.append('Authorization', 'jwt ' + authToken.value)
        })
      ).pipe(tap((response: HttpResponse<any>) => {
        console.log(response);
        if (response instanceof HttpResponse) {
          if (response.body.status == 401) {
            this._router.navigate([Routes.LOGIN]);
            return response;
          }
        }
      }));
    }
    this._router.navigate(['/login']);
  }
}

This process is working , but whenever the route is changed i get this in the chrome dev console : ERROR You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.

How do i prevent this ? and what am i doing wrong ?


Solution

  • Thank you @Julien For pointing me to the right direction. After looking at the answer , i did a bit more digging in search of solution and the below is the solution that worked for me

    @Injectable()
    export class AuthInterceptorService implements HttpInterceptor {
    
      constructor(private _localStorageService: LocalStorageService, private _router: Router, private _location: Location) { }
    
    
      intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        if (req.url.includes("/login")) {
          return next.handle(req);
        }
        let authToken: LocalStorage = this._localStorageService.getItem('auth-token');
        if (authToken) {
          return next.handle(
            req.clone({
              headers: req.headers.append('Authorization', 'jwt ' + authToken.value)
            })
          ).pipe(tap((response: HttpResponse<any>) => {
            console.log(response);
            if (response instanceof HttpResponse) {
              if (response.body.status == 401) {
                this._router.navigate([Routes.LOGIN]);
                return response;
              }
            }
          }));
        }
        this._router.navigate(['/login']);
        return empty();
      }
    }
    

    If anyone comes across this issue refer : Angluar2 routing inside http interceptor

    The accepted answer does not use the http interceptor but there is another answer that uses interceptor

    The Solution that i used is just return an empty observable using empty()