Búsqueda de sitios web

javascript - Interceptor de Angular para excluir URLs específicas


Estoy escribiendo interceptores de manera que no tenga que manejar los encabezados en cada servicio que llama a mi API web. El problema con esto es que el 99% de mis llamadas requieren 1 conjunto específico de encabezados, pero el otro 1% solo requiere 1 de los encabezados y no funcionará si los otros están presentes. Sabiendo esto, mi idea es hacer 2 interceptores: el primero añadirá el 1 encabezado que todos usan y el segundo añadirá el resto de los encabezados, excluyendo en el segundo el 1%.

Lo siguiente es cómo estoy excluyendo el 1%, lo cual funciona, pero quiero ver si hay una mejor manera de hacerlo:

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
    }
  }

Respuesta #1

Actualización desde Angular 12, usa "contexto", consulta este SO

Sugiero que, a pesar de revisar la solicitud, puedes usar el encabezado para agregar una propiedad "skip", si el encabezado tiene la propiedad skip, simplemente devuelve los reqs

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

Y haces todas las llamadas que necesitas "omitir" el interceptor como

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

Respuesta #2

después de comprobar req.headers.get("skip") como sugirió Eliseo, recomendaría eliminar este encabezado de la solicitud ya que solo está relacionado con Angular y no debería transmitirse a la API (en realidad puede causar problemas)

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

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

Respuesta #3

Lo que terminé haciendo fue tener un arreglo de URLs (en formato Regex) que no quería que se usaran en el interceptor de la siguiente manera:

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;
  }
}

Respuesta #4

Cuando se crea por defecto, HttpClient usará un interceptor. Si quieres evitar esto, puedes crear otra instancia de HttpClient usando el constructor.

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

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

La instancia customHttpClient no utilizará el interceptador.

Artículos relacionados