3

I am trying to write an HTTP interceptor to add an 'access level' parameter to the request. I am trying to get the value from an observable currentAccessLevel$. However, the observable is not returned correctly and the interceptor breaks the entire request cycle.

This question already has an answer here and here, however, the accepted answers do not seem to be working in Angular 8. I am not sure if I'm doing something wrong or if there was some sort of change made to interceptors in Angular 8.

I also tried using switchMap, flatMap, and mergeMap.

import { Injectable } from '@angular/core';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor
} from '@angular/common/http';
import { Observable } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { AuthService } from 'src/app/services/auth/auth.service';

@Injectable()
export class AccessLevelInterceptor implements HttpInterceptor {
  private accessLevel: string;

  constructor(private authService: AuthService) { }

  // Intercept HTTP Requests
  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

    // Get current value of access level observable from authentication service
    return this.authService.currentAccessLevel$
      .mergeMap(res => next.handle(request));

  }

}

The currentAccessLevel$ is a string value created in a service as a BehaviorSubject and then converted to an Observable. That way the current value of the string can be shared across multiple components.

// Create a BehaviorSubject to track and share updates to currentAccessLevel value
  private currentAccessLevel: string;
  currentAccessLevelSubject: BehaviorSubject<string> = new BehaviorSubject(this.currentAccessLevel);
  currentAccessLevel$ = this.currentAccessLevelSubject.asObservable();
pengz
  • 2,279
  • 3
  • 48
  • 91
  • 1
    Just interested. what does currrentAccessLevel$ return and do. Will it add something to the request ? – Jens Alenius Sep 16 '19 at 15:11
  • @JensAlenius It's just a string created in a service with a BevhaviorSubject and converted to an Observable, that way it can be shared across multiple components. Updated the question with these details. – pengz Sep 16 '19 at 15:26
  • 1
    Thx. But will it do something to the request it intercepts? I'm not getting the Rxjs part of it. (It been a long day for me :) ) – Jens Alenius Sep 16 '19 at 15:38
  • @JensAlenius Yep this is just a minimal code snippet shown above. Inside the body of merge map, it will check if the currentAccessLevel is set and if the user is an admin. A new parameter will be added to the request to set the current access level which will modify the query on the backend. This feature is in place for an admin to be able to change their current access level for example. – pengz Sep 16 '19 at 15:42
  • 1
    Aha! Now I understand – Jens Alenius Sep 16 '19 at 22:11
  • 1
    You one last comment. You might be able to skip currentAccessLevel$. You could use only a string property in authService. This would simplify the code and you would not need to do a pipe and mergeMap. I have both ordinary properties and observable in my service depending on the case. I only use observables if I do a httpcall or if I use a subscribe/observe pattern.in the service. – Jens Alenius Sep 17 '19 at 05:43
  • @JensAlenius Thank you for the thoughtful feedback. I changed currentAccessLevel observable to a string variable stored in SessionStorage instead. That way the value persists after the browser refresh and the user can switch the value during the session. – pengz Sep 17 '19 at 14:08

1 Answers1

2

Yes, this is not working anymore since Rxjs 5.5. You need to use pipe method to concatenate operators:

return this.authService.currentAccessLevel$
      .pipe(mergeMap(res => next.handle(request)));

Take a look here to learn more about piping.

Federico Galfione
  • 1,069
  • 7
  • 19