【问题标题】:Angular interceptor exclude specific urls角度拦截器排除特定网址
【发布时间】:2019-04-04 17:59:23
【问题描述】:

我正在编写拦截器,这样我就不必处理调用我的 web api 的每个服务中的标头。这样做的问题是,我 99% 的调用需要 1 组特定的标头,但其他 1% 只需要 1 个标头,并且不能与其他存在的标头一起使用。知道了这一点后,我的想法是制作 2 个拦截器,第一个将添加它们都使用的 1 个标头,第二个将添加其余的标头,第二个不包括 1%。

以下是我排除 1% 的方法,这是可行的,但我想看看是否有更好的方法来解决这个问题:

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

【问题讨论】:

标签: javascript angular typescript


【解决方案1】:

从 Angular 12 更新,使用“上下文”,见SO

我建议,尽管检查请求,你可以使用header添加一个“skip”属性,如果header有skip属性,简单返回reqs

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

然后你进行所有你需要的调用“跳过”拦截器,比如

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

【讨论】:

  • 对不起我的愚蠢。我在网上找不到选项{headers:{skip:"true"}
  • 您可以添加任何您想要的标题。我喜欢“skip”这个名字,但你可以选择任何东西(例如,在某些电子商务平台中,你可以添加一些 API-KEY)
【解决方案2】:

我最终做的是有一个我不想在拦截器中使用的 url 数组(正则表达式格式),如下所示:

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

【讨论】:

    【解决方案3】:

    按照 Eliseo 的建议检查 req.headers.get("skip") 后,我建议从请求中删除此标头,因为它仅与 Angular 相关,不应传输到 API(实际上它可能会导致问题)

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

    【讨论】:

      【解决方案4】:

      默认创建时,HttpClient 将使用拦截器。如果你想避免这种情况,你可以使用构造函数创建另一个 HttpClient 实例。

      @Injectable()
      class Service {
        private customHttpClient: HttpClient;
      
        constructor(backend: HttpBackend) {
          this.customHttpClient = new HttpClient(backend);
        }
      }

      customHttpClient 实例不会使用拦截器。

      【讨论】:

      • 我认为这是最好的直接方法
      【解决方案5】:

      您可以尝试扩展 HttpClient 而不是使用拦截器。

      拦截器世界中,每个请求都会在执行之前停止 - 按摩(添加标头)。

      HttpClient World 中,它会在客户端对象实例化时得到处理。

      如果您认为有必要,您可以考虑使用不同的变体本身,HttpClient99Percent 变体,HttpClientOnePercent 变体等。

      下面的链接可以让你抢先一步:

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

      【讨论】:

        【解决方案6】:

        Андрей Керничный'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/');
          }
        }
        

        【讨论】:

          猜你喜欢
          • 2017-01-28
          • 2023-03-16
          • 2017-10-09
          • 1970-01-01
          • 2016-02-02
          • 2014-10-25
          • 2020-11-20
          • 2018-03-10
          • 2019-07-09
          相关资源
          最近更新 更多