Redirect and cancel request using Interceptor when HttpStatus is 202

5.8k Views Asked by At

I'm doing a web application using Angular 10.

In my authentication flow, if the backend sends HttpStatus 202 after you log in, means that you need to enter a pincode and I need to redirect you to another component. I have tried to do this using an Interceptor but, I am experiencing the following problems:

  1. The redirection is not happening
  2. I cannot find a way to cancel the request, in other words, let the owner of the request (LoginComponent) to know that it needs to do nothing because something else happened.

Interceptor

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

  constructor(
    private router: Router
  ) {
  }

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(request).pipe(
      filter(event => event instanceof HttpResponse),
      map((event: HttpResponse<any>) => {
        if (event.status === 202) {
          this.router.navigateByUrl('/validation-code');
        }
        return event;
      }));
  }

}

LoginComponent

@Component({
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit {

  constructor(
    private authService: AuthService,
    private router: Router
  ) {
  }

  onSubmit() {
    this.authService.login('username', 'password')
      .pipe(first())
      .subscribe(() => this.router.navigate(['/']));
  }

}

AuthService

login(username: string, password: string): Observable<IUser> {
    const payload = {
      Username: username,
      Password: password,
    };

    return this.post<IUser>({
      url: '/login',
      body: payload
    })
      .pipe(
        tap(user => this.localStorageService.set('user', user)),
      );
  }

I have tried to modify the Interceptor like this:

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(request).pipe(
      filter(event => event instanceof HttpResponse),
      map((event: HttpResponse<any>) => {
        if (event.status === 202) {
          this.router.navigateByUrl('/auth/validation-code');

          // I have tried these...
          // return of(undefined);
          // return EMPTY;
          // return NEVER;
        }
        return event;
      }));

  }

TS2322: Type 'Observable<HttpResponse | Observable>' is not assignable to type 'Observable<HttpEvent>'.   Type 'HttpResponse | Observable' is not assignable to type 'HttpEvent'.     Type 'Observable' is not assignable to type 'HttpEvent'.       Property 'type' is missing in type 'Observable' but required in type 'HttpUserEvent'.

My goal is to handle my scenarios of authentication using an Interceptor and redirect the user to a component when I receives HttpStatus 202.

1

There are 1 best solutions below

0
On

You need to throw an error in order to stop the observable flow. Try this:

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(request).pipe(
      filter(event => event instanceof HttpResponse),
      map((event: HttpResponse<any>) => {
        if (event.status === 202) {
          this.router.navigateByUrl('/auth/validation-code');
          throw new Error('Pin code required');
        }
        return event;
      }),
      catchError(err => {
        return of(err);
      })
    );
  }