SGR
SGR

Reputation: 2427

Call common api before intercept fires

My interceptor code:

    import { Injectable } from '@angular/core';
    import {
      HttpInterceptor,
      HttpRequest,
      HttpHandler,
      HttpEvent,
      HttpErrorResponse,
      HttpHeaders,
      HttpResponse
    } from '@angular/common/http';
    import { Observable, throwError } from 'rxjs';
    import { catchError, map } from 'rxjs/operators';
    import { ApiService } from 'src/app/modules/services/api.service';
    import { Router } from '@angular/router';
    
    
    @Injectable({
      providedIn: 'root'
    })
    export class HttpErrorService implements HttpInterceptor {
      constructor(
        private apiService: ApiService,
        private router: Router,
      ) { }
    
      intercept(request: HttpRequest<any>,next: HttpHandler): Observable<HttpEvent<any>> {
    
        request = request.clone({
          headers: new HttpHeaders({
            'Content-Type':  'application/json',
            'Accept': 'application/json',
            'Access-Control-Allow-Headers': 'Content-Type',
          })
        });
        
        return this.apiService.getSession().subscribe((res:any)=>{
           if(res.data.existingSession == 'active'){
              this.router.navigate(['/login']);
           } else{
            return next.handle(request).pipe(
              map((event: HttpEvent<any>) => {
                return event;
              }),
              catchError((error: HttpErrorResponse) => {
                return throwError(() => { return 'Something bad happened; please try again later.' })
              }));
           }
        });
    
    
      }
    }

I am trying to call an api before the interceptor intercept each api calls. But I am unable to add the valid return type & getting this error:

Type 'Subscription' is missing the following properties from type 'Observable<HttpEvent>': source, operator, lift, subscribe, and 3 more

Tried with switchMap.

import { Injectable } from '@angular/core';
import {
  HttpInterceptor,
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpErrorResponse,
  HttpHeaders,
  HttpResponse
} from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
import { ApiService } from 'src/app/modules/services/api.service';
import { Router } from '@angular/router';
@Injectable({
  providedIn: 'root'
})
export class HttpErrorService implements HttpInterceptor {
  constructor(
    private apiService: ApiService,
    private router: Router,
  ) { }

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    request = request.clone({
      headers: new HttpHeaders({
        'Content-Type':  'application/json',
        'Accept': 'application/json',
        'Access-Control-Allow-Headers': 'Content-Type',
      })
    });

    return this.apiService.getSession().pipe(
      switchMap((res: any) => {
        if(res.data.existingSession == 'active'){
          this.router.navigate(['/login']);
        } else{
          return next.handle(request).pipe(
            map((event: HttpEvent<any>) => {
              return event;
            }),
            catchError((error: HttpErrorResponse) => {
              return throwError(() => 'Something bad happened; please try again later.');
            })
          );
        })
        }
    );
  }
}

It's triggering the interceptor n number of time. But api calls are not happening. I need to call 1 api before interceptor intercepts each api calls.

Upvotes: 3

Views: 242

Answers (2)

Oscar F
Oscar F

Reputation: 1149

Here is code example on stackblitz based on code you provided in your question. I think this would solved your problem.

If you want to use service api in interceptor I think you need to be sure that this api would be executed without using this interceptor; and the best or default way to do that is to use HttpBackend. of course you can see usage in this code example.

Just a note, I see you tried to use router.navigate() in your interceptor and I think it's not the best place for this kind of control. I can understand the need to define some logic through interceptor, but if you want to handle route redirection(related to session management) Angular guard would be better for that.

Hope this could be helpful.

Upvotes: 3

Naren Murali
Naren Murali

Reputation: 57986

I tried this example for a long time and then realized its not a good method to do, because, http interceptor is meant to intercept http requests, at the place of intercepting, its not right not make another http call, this will create a never ending loop (sometimes browser will crash)

Ideally, you need to send the auth token during each api call and API call should give 401 (un authorized error) during this, we need to navigate to login page.

If your API does not support auth over each api call, kindly check the auth using a setInterval or rxjs interval at regular intervals and logout the application

Approach 1 is ideal, but as a temporary fix, you can implement approach 2.

So to summarize, its better not to do this, due to above mentioned reasons!

Upvotes: 1

Related Questions