Angular4 httpclient 仅针对特定服务的拦截器

Angular4 httpclient 仅针对特定服务的拦截器,angular4-httpclient,Angular4 Httpclient,我的应用程序中有几个指向不同API URL的服务。现在我需要为每个服务设置不同的头。我现在的问题是关于Angular 4中的新拦截器。是否有可能为特定服务设置一个拦截器?那么每个服务都有其特定的拦截器 希望你们能理解我的问题。一旦新的HttpClient发出请求/响应,所有的拦截器都将被调用。您可以做的一件事是标记您的请求,以便在设计用于处理该请求的拦截器中设置正确的标头。TL:DR Answer: 不,没有办法。拦截器用于拦截所有请求 长答覆: 存储库和请求都不应该知道它可以传递的拦截器。因此

我的应用程序中有几个指向不同API URL的服务。现在我需要为每个服务设置不同的头。我现在的问题是关于Angular 4中的新拦截器。是否有可能为特定服务设置一个拦截器?那么每个服务都有其特定的拦截器


希望你们能理解我的问题。

一旦新的HttpClient发出请求/响应,所有的拦截器都将被调用。您可以做的一件事是标记您的请求,以便在设计用于处理该请求的拦截器中设置正确的标头。

TL:DR Answer:

不,没有办法。拦截器用于拦截所有请求

长答覆:

存储库和请求都不应该知道它可以传递的拦截器。因此,我不同意标记请求或检查特定类的解决方案

我更喜欢这里提供的解决方案:

基本上,如果应该添加特定的头,拦截器必须检查服务(中介模式)

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    console.log(JSON.stringify(req));

    const token: string = this.currentUserService.token;

    if (token) {
        req = req.clone({ headers: req.headers.set('Authorization', 'Bearer ' + token) });
    }

    if (!req.headers.has('Content-Type')) {
        req = req.clone({ headers: req.headers.set('Content-Type', 'application/json') });
    }

    req = req.clone({ headers: req.headers.set('Accept', 'application/json') });
    return next.handle(req);
}
intercept(req:HttpRequest,next:HttpHandler):可观察{
log(JSON.stringify(req));
const token:string=this.currentUserService.token;
如果(令牌){
req=req.clone({headers:req.headers.set('Authorization','Bearer'+token)});
}
如果(!req.headers.has('Content-Type')){
req=req.clone({headers:req.headers.set('Content-Type','application/json'))});
}
req=req.clone({headers:req.headers.set('Accept','application/json'))});
返回next.handle(req);
}
这是一个很好的例子,但要注意它违反了单一责任原则(设置多个标题)

除此之外,我的观点是,拦截器是解决问题的错误模式。我也不认为拦截器是向请求添加承载令牌的解决方案。这就是我的用例,它把我带到了这里

基本上,我会质疑您的架构,并重新思考如何创建请求。此问题的解决方案可以是以下设计:

抽象存储库

具有返回HttpRequest的get/post/put等基本方法

有一个名为“send”的方法,该方法接受HttpRequest作为参数

混凝土存储库

从抽象存储库继承并扩展基本请求函数

因此,对于您的用例,您有一个基本服务,每个特定/自定义服务都继承自这个扩展您请求行为的特定服务

装饰师

为了使这个体系结构更进一步(正如我所做的),您可以创建一个typescript装饰器(在所有情况下都不可能,例如,当需要依赖注入时),它扩展了所有装饰函数的行为。例如,添加特定的标题。这可能是这样的:

从'rxjs/Observable'导入{Observable};
从'@angular/common/http'导入{HttpClient,HttpRequest,HttpEvent};
从“@angular/core”导入{Injectable};
导出抽象类BaseRepository{
构造函数(受保护的客户端:HttpClient){
}
公共createGetRequest(url:string):HttpRequest{
返回新的HttpRequest(“GET”,url);
}
公共发送(请求:HttpRequest):可观察{
返回此.client.request(request);
}
}
@可注射()
导出类NormalServiceRepository扩展了BaseRepository{
构造函数(受保护的客户端:HttpClient){
超级(客户);
}
公共get(url:string):可观察{
const baseRequest=super.createGetRequest(url);
baseRequest.headers.set('Content-Type','application/json');
返回此。发送(baseRequest);
}
}
@可注射()
导出类AuthServiceRepository扩展了BaseRepository{
构造函数(受保护的客户端:HttpClient){
超级(客户);
}
@AcceptsJson()
@SendsJson()
@转发凭据()
公共createGetRequest(url:string):HttpRequest{
返回super.createGetRequest(url);
}
公共get(url:string):可观察{
const baseRequest=super.createGetRequest(url);
返回此。发送(baseRequest);
}

}
这个问题有点晚了,但这对我们来说很有效。是的,它进入拦截器,但是一个简单的条件可以使它不执行

 intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // Do not execute interceptor
    if (some condition)
      return next.handle(req);

    // Else.. do your thing and go next...
    // Add headers, modify reqyest, etc..
    return next.handle(req);
  }
intercept(req:HttpRequest,next:HttpHandler):可观察{
//不要执行拦截器
如果(某些条件)
返回next.handle(req);
//否则…做你的事,然后继续。。。
//添加标题、修改请求等。。
返回next.handle(req);
}

实际上有一种方法可以为特定的服务设置拦截器。请注意重点,因为它实际上不是
HttpInterceptor
接口的实现

TL:DR-跳转到底部的示例

HttpClient
实际上只通过所有可能的方法将输入转换为一个名为
HttpRequest
的结构,然后将该结构传递给
HttpHandler
实现。顾名思义,它负责处理HTTP请求。
HttpHandler
实现中,您可以找到例如
HttpInterceptingHandler
(运行拦截器链)或
HttpXhrBackend
(通过
HttpBackend
类继承,此处理程序是最后一个实际发送XHR请求的处理程序)。如果您查看一下,就会发现它实际上取决于后者(间接地,在
HttpBackend
标记下,
HttpXhrBackend
作为默认实现提供)。所以就像拦截器一样,Angular通过DI链接处理程序,最后一个是执行请求的后端

您可以做的是添加另一个处理程序