3

I have Multiple API in a single component, where on token expire interceptor runs multiple times, for example, if I have 4 GET API in a single component then 4 times interceptor will run on token expire

Below is the code for interceptor

my.httpInterceptor.ts

import {
  Injectable
} from "@angular/core";
import {
  tap
} from "rxjs/operators";
import {
  ToastyService,
  ToastOptions
} from 'ng2-toasty';
import {
  Router
} from "@angular/router";
import {
  _throw
} from 'rxjs/observable/throw';
import 'rxjs/add/operator/do';
import 'rxjs/Observable';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor,
  HttpResponse,
  HttpErrorResponse,
  HttpHeaders
} from "@angular/common/http";
import {
  Observable
} from "rxjs/Observable";

@Injectable()
export class MyInterceptor implements HttpInterceptor {
  constructor(private router: Router, private toastyService: ToastyService, ) {}

  //function which will be called for all http calls
  intercept(
    request: HttpRequest < any > ,
    next: HttpHandler
  ): Observable < HttpEvent < any >> {
    //how to update the request Parameters
    if (JSON.parse(localStorage.getItem('userDetails'))) {
      let authToken = JSON.parse(localStorage.getItem('userDetails'));
      if (authToken.currentUserToken != null) {
        const authReq = request.clone({
          headers: new HttpHeaders({
            'Content-Type': 'application/json',
            'Authorization': 'Bearer' + authToken.currentUserToken
          })
        });
        return next.handle(authReq)
          .catch((err) => {
            if (err) {
              let errorCodes = [404, 500, 422, 412, 424, 409];
              if (errorCodes.includes(err.status)) {
                let toastOptions: ToastOptions = {
                  title: "Error",
                  msg: "Error",
                  showClose: true,
                  timeout: 5000,
                  theme: 'default'
                };
                toastOptions.msg = err.error.errors.name;
                this.toastyService.error(toastOptions);
              }
              if (err.status === 401) {
                this.router.navigate(['/']).then((nav) => {
                  // debugger;
                  if (nav) {
                    if (this.router.url === '/') {
                      setTimeout(() => {
                        let toastOptions: ToastOptions = {
                          title: "Session Expired",
                          msg: "Please login again to access",
                          showClose: true,
                          timeout: 5000,
                          theme: 'default',
                        }
                        // toastOptions.msg = "Session Expired";
                        this.toastyService.error(toastOptions);
                      });
                    }
                  }
                });
              }
              return _throw(err.message);
            }
          });
      }
    } else {
      const updatedRequest = request.clone({
        headers: new HttpHeaders({
          'Content-Type': 'application/json',
        })
      });
      return next.handle(updatedRequest)
    }
  }


}

How to avoid calling interceptor multiple times.

1 Answer 1

1

Interceptors are invoked for all outgoing http requests. However, you can filter the request URLs you want to apply your logic:

@Injectable()
export class MyInterceptor implements HttpInterceptor {
  constructor(private router: Router, private toastyService: ToastyService) {
  }

  //The API you want to intercept its requests (you could take it from a global constants file)
  API_URL = "http://www.example.com/host/to/intercept";

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

    //only get the token from localStorage when the request points to the API that needs authorization
    if (request.url === this.API_URL) {
      let userDetails = localStorage.getItem('userDetails');
      if (userDetails != null) {
        let authToken = JSON.parse(userDetails);
        if (authToken.currentUserToken != null) {
          const authReq = request.clone({
            headers: new HttpHeaders({
              'Content-Type': 'application/json',
              'Authorization': 'Bearer' + authToken.currentUserToken
            })
          });
          return next.handle(authReq)
          .catch((err) => {
            if (err) {
              let errorCodes = [404, 500, 422, 412, 424, 409];
              if (errorCodes.includes(err.status)) {
                let toastOptions: ToastOptions = {
                  title: "Error",
                  msg: "Error",
                  showClose: true,
                  timeout: 5000,
                  theme: 'default'
                };
                toastOptions.msg = err.error.errors.name;
                this.toastyService.error(toastOptions);
              }
              if (err.status === 401) {
                this.router.navigate(['/']).then((nav) => {
                  // debugger;
                  if (nav) {
                    if (this.router.url === '/') {
                      setTimeout(() => {
                        let toastOptions: ToastOptions = {
                          title: "Session Expired",
                          msg: "Please login again to access",
                          showClose: true,
                          timeout: 5000,
                          theme: 'default',
                        }
                        // toastOptions.msg = "Session Expired";
                        this.toastyService.error(toastOptions);
                      });
                    }
                  }
                });
              }
              return _throw(err.message);
            }
          });
        }
      } else {
        const updatedRequest = request.clone({
          headers: new HttpHeaders({
            'Content-Type': 'application/json',
          })
        });
        return next.handle(updatedRequest);
      }
    }
  }
}
Sign up to request clarification or add additional context in comments.

2 Comments

Please, can you elaborate the functionality bit more?
Done. Basically you need to filter (by URL) outgoing requests that need authorization (pointing to an authenticated API) and add the token only to them. The token check will not be done in the requests going to another API.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.