'Angular interceptor exclude specific urls

I am writing interceptors such that I don't have to handle the headers in every service calling my web api. The problem with this is that 99% of my calls require 1 specific set of headers, but the other 1% only require 1 of the headers and will not work with the others present. With this being known my idea is to make 2 interceptors, the first will add the 1 header that they all use and the second will add the rest of the headers, with the second excluding the 1%.

The following is how I am going about excluding the 1%, which works, but I want to see if there is a better way of going about this:

intercept(request: HttpRequest<any>, next:HttpHandler: Observable<HttpEvent<any>> {
  let position = request.url.indexOf('api/');
  if (position > 0){
    let destination: string = request.url.substr(position + 4);
    let matchFound: boolean = false;

    for (let address of this.addressesToUse){
      if (new RegExp(address).test(destination)){
        matchFound = true;
        break;
      }
    }

    if (!matchFound){
      ...DO WORK to add the headers
    }
  }


Solution 1:[1]

What I wound up doing is having an array of urls (in Regex Format) that I did not want to be used in the interceptor like so:

import { Injectable } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable()
export class AddCustomHeadersInterceptor implements HttpInterceptor {
  urlsToNotUse: Array<string>;

  constructor(
  ) {

    this.urlsToNotUse= [
      'myController1/myAction1/.+',
      'myController1/myAction2/.+',
      'myController1/myAction3'
    ];
  }

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if (this.isValidRequestForInterceptor(request.url)) {
      let modifiedRequest = request.clone({
        setHeaders: {
          //DO WORK HERE
        }
      });

      return next.handle(modifiedRequest);
    }
    return next.handle(request);
  }

  private isValidRequestForInterceptor(requestUrl: string): boolean {
    let positionIndicator: string = 'api/';
    let position = requestUrl.indexOf(positionIndicator);
    if (position > 0) {
      let destination: string = requestUrl.substr(position + positionIndicator.length);
      for (let address of this.urlsToNotUse) {
        if (new RegExp(address).test(destination)) {
          return false;
        }
      }
    }
    return true;
  }
}

Solution 2:[2]

Update from Angular 12, use "context", see this SO

I suggest that, in spite of check the request, you can use the header to add a "skip" property, if the header has the skip property, simple return the reqs

export class CustomInterceptor implements HttpInterceptor {
    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        if (req.headers.get("skip"))
           return next.handle(req);
      
        ....
    }
}

And you make all the calls you need "skip" the interceptor like

this.http.get(url, {headers:{skip:"true"});

Solution 3:[3]

after checking for req.headers.get("skip") as Eliseo suggested, I'd recommend removing this header from request since it's Angular-related only and it should not be transmitted to the API (actually it can cause issues)

const skipIntercept = request.headers.has('skip');

if (skipIntercept) {
    request = request.clone({
        headers: request.headers.delete('skip')
    });
}

Solution 4:[4]

When created by default, HttpClient will use interceptor. If you want to avoid this, you can create another instance of HttpClient using constructor.

@Injectable()
class Service {
  private customHttpClient: HttpClient;

  constructor(backend: HttpBackend) {
    this.customHttpClient = new HttpClient(backend);
  }
}

The customHttpClient instance will not use the interceptor.

Solution 5:[5]

You can try to extent HttpClient instead of using Interceptors.

In an Interceptor World every request is stopped - massaged (headers are added) - before executed.

In a HttpClient World it would be taken care at the time of Client object instantiation.

If you deem it necessary, you can consider having different variants per se, HttpClient99Percent variant, HttpClientOnePercent variant etc.

Below link can give you a head start:

https://medium.com/@admin_87321/extending-angular-httpclient-6b33a7a1a4d0

Solution 6:[6]

update of ?????? ?????????'s answer

import { Injectable } from '@angular/core';
import { HttpClient, HttpBackend } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class CartService {
  private customHttpClient: HttpClient;

  constructor(private http: HttpClient, backend: HttpBackend) { 
    this.customHttpClient = new HttpClient(backend);
  }

  getZohoItems() {
    // call zoho url
    return this.customHttpClient.get('http://zoho.com/api/orders/');
  }

  getItems() {
    // call localhost:8000 url
    return this.http.get('/api/orders/');
  }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 dmoore1181
Solution 2
Solution 3
Solution 4 Myk Willis
Solution 5 takrishna
Solution 6 suhailvs