【问题标题】:How to add HttpClient Interceptors conditionally in Angular如何在 Angular 中有条件地添加 HttpClient 拦截器
【发布时间】:2018-01-28 14:24:01
【问题描述】:

最近我一直在使用带有 Angular HttpClient 的拦截器。

我添加了与某些 HTTP GET 方法相对应的标头,对于一些我不需要这些标头。

如何告诉我的拦截器有条件地将拦截器添加到这些方法?我什至可以拆分服务,例如一项服务用于标头,一项服务没有标头,或者一项用于不同标头,另一项用于不同标头。

NgModule 提供者

{
  provide: HTTP_INTERCEPTORS,
  useClass: AuthInterceptor,
  multi: true,
},{
  provide: HTTP_INTERCEPTORS,
  useClass: AngularInterceptor,
  multi: true,
}

我的拦截器

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const authReq = req.clone({headers: req.headers.set('X-Auth-Token', "-------------------------")});
    return next.handle(authReq);

  }
}


@Injectable()
export class AngularInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(req).do(event => {}, err => {
        if(err instanceof HttpErrorResponse){
            console.log("Error Caught By Interceptor");
            //Observable.throw(err);
        }
    });
  }
}

【问题讨论】:

  • 请求拦截器添加标头的逻辑应该在拦截器中
  • @jonrsharpe 在我与 httpclient 一起实现 http 拦截器时在内部调用。
  • 我不确定你的意思;我知道新的拦截器是如何工作的(我有written about them)。我的意思是 拦截器本身 应该包含指定需要将标头添加到哪些请求的逻辑,根据设计,每个请求都会调用 intercept 方法。
  • @jonrsharpe 对不起,我当时听不懂你的说法。所以这就像添加一堆 if else 的 switch 来检查 req 并添加标题对吗?
  • 是的,没错。这样,其他所有内容都可以发出请求,而不必担心是否添加或应该添加标头。

标签: angular angular-http angular-http-interceptors angular-httpclient


【解决方案1】:

注意:我自己还没有尝试过这种方法,但已经尝试过这个想法,因为我们正在研究一个类似的问题。

如果我们有非常简单的需求,在通用拦截器中添加逻辑并根据 URL/Method 决定执行哪种拦截将是微不足道的。但是,我们的 Angular 应用需要调用各种对拦截器有不同要求的 1 方微服务和 3 方 API。这实际上是您的要求的超集。

实现这一点的一个想法是为我们需要调用的每个 API/Service 扩展 HttpClient 并为拦截器链设置自定义注入令牌。可以看到angular是如何注册默认的HttpClienthere的:

 providers: [
    HttpClient,
    // HttpHandler is the backend + interceptors and is constructed
    // using the interceptingHandler factory function.
    {
      provide: HttpHandler,
      useFactory: interceptingHandler,
      deps: [HttpBackend, [new Optional(), new Inject(HTTP_INTERCEPTORS)]],
    },

interceptingHandler 函数甚至是 exportedɵinterceptingHandler。我同意这看起来有点奇怪,不知道为什么它有那个出口名称。

无论如何,要使用自定义 HttpClients,您可能可以:

export const MY_HTTP_INTERCEPTORS = new InjectionToken<HttpInterceptor[]>('MY_HTTP_INTERCEPTORS');

...
 providers: [
    MyHttpClient,
    {
      provide: MyHttpHandler,
      useFactory: interceptingHandler,
      deps: [HttpBackend, [new Optional(), new Inject(MY_HTTP_INTERCEPTORS)]],
    },

并确保MyHttpClient 在其构造函数中需要MyHttpHandler

【讨论】:

【解决方案2】:

我知道为时已晚,但是我们仍然没有来自 Angular 的任何解决方案。 目前一个简单的解决方法是创建一个 BehaviorSubject 并根据它的值激活拦截器。这样,您就可以处理必须使用拦截器的特定 HTTP 请求:

yourService.service.ts

public interceptorTwo = new BehaviorSubject<boolean>(null);

someHttpmethod() {
   this.interceptorTwo.next(true);

   // Add your CODE http
   this.myHttp.post<any>('someUrl', data).finally(() => this.interceptorTwo.next(null));
}

yourInterceptorTwo.service.ts

const setAuth = this.yourService.interceptorTwo.value;
if (!setAuth) {
  return next.handle(req);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-10
    • 1970-01-01
    • 1970-01-01
    • 2021-11-27
    • 2018-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多