Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 6 handling of 403 response with new RxJS

THE PROBLEM:

I have an interceptor:

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

  constructor(private injector: Injector, private router: Router) {
  }


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

    const auth = this.injector.get(AuthenticationService);
    const authHeaders = auth.getAuthHeader();
    const authReq = request.clone({headers: authHeaders});

     return next.handle(authReq).do((event: HttpEvent<any>) => {
       if (event instanceof HttpResponse) {

       }
     }, (err: any) => {
       if (err instanceof HttpErrorResponse) {
         if (err.status === 403) {
           this.router.navigate(['login']);
         }
       }
     });
  }
}

it was wornking in Angular 5, but now i've migrated to 6 and this doesn't work anymore.

It says property 'do' doesn't exist on type Observable.

Also i've tried to implement the solution from this thread: LINK Didn't work as well.

This topic says it is consequence of rxjs changes. After making suggested changes the problem remains (now with 'tap' instead 'do')

here is import section:

// import {Observable} from "rxjs/Observable";
import {Observable} from "rxjs/Rx";
import { tap } from 'rxjs/operators';

Note: commented line has been tried as well.

like image 210
Unknwn Artist Avatar asked Nov 08 '22 06:11

Unknwn Artist


1 Answers

To get this working for my project (Angular 6, RxJS 6) I had to make the following changes:

import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor, HttpResponse, HttpErrorResponse } from '@angular/common/http';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
import { Router } from '@angular/router';

And modify the snippet from above to be:

(chaining changed to piping, and changed 'do' to 'tap')

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

  constructor(private injector: Injector, private router: Router) {
  }


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

    const auth = this.injector.get(AuthenticationService);
    const authHeaders = auth.getAuthHeader();
    const authReq = request.clone({headers: authHeaders});

     return next.handle(authReq).pipe(
       tap((event: HttpEvent<any>) => {
         if (event instanceof HttpResponse) {

         }
       }, (err: any) => {
         if (err instanceof HttpErrorResponse) {
           if (err.status === 403) {
             this.router.navigate(['login']);
           }
         }
       })
   );
  }
}

The reason for this are some recent changes in RxJS 6.

Use piping instead of chaining as new operator syntax. The result of one operator is piped into another operator.

And

Note Some operators have a name change due to name collisions with JavaScript reserved words! These include: do -> tap, catch -> catchError, switch -> switchAll, finally -> finalize.

like image 93
Jbrown Avatar answered Nov 15 '22 11:11

Jbrown