(可选)在角度4中应用HTTP拦截器 [英] Optionally apply http interceptors in angular 4

查看:74
本文介绍了(可选)在角度4中应用HTTP拦截器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下网址介绍了如何在Angular 4中使用http拦截器: https ://angular.io/guide/http#intercepting-all-requests-or-responses

The following url explained how to use http interceptor in Angular 4: https://angular.io/guide/http#intercepting-all-requests-or-responses

但是,我想知道是否有任何方法可以选择是否使用拦截器?还是选择使用哪组拦截器?我想实现一组身份验证拦截器,但是,当用户访问不需要用户身份验证的loginsignupforget-password之类的东西时,我不希望应用这些拦截器.

However, I'm wondering whether there is any way to choose whether to use the interceptors or not? Or to choose which set of interceptors to use? I want to implement a set of authentication interceptors, however, I don't want these interceptors to be applied when users access things like login, signup and forget-password which do not need user authentication.

如果需要,我所需要的只是将HttpClient的干净实例注入到我的服务中.我不喜欢只能使用被所有拦截器污染的HttpClient单个全局实例的方式.

All I need is to inject a clean instance of HttpClient into my service, if I need. I don't like the way that I can only use a single global instance of HttpClient that is being polluted by all interceptors.

推荐答案

我有相同的要求,并提出了以下解决方案.

I had this very same requirement and came up with the following solution.

在模块中,我使用令牌提供"一个HttpClient,如下所示.

In the Module, I 'provide' an HttpClient using a Token as follows.


    export const HTTP_NOAUTH = new InjectionToken("http_noauth");
    ...
    providers: [...,
    {
        provide: HTTP_NOAUTH,
        deps: [HttpBackend],
        useFactory: (handler: HttpBackend) => {
            return new HttpClient(handler);
        }
    },
    {
        provide: HTTP_INTERCEPTORS,
        useClass: AuthHttpInterceptor,
        multi: true
    }],
    ...

然后,当我注入HttpClient并不想使用AuthHttpInterceptor时,我指定了'@Inject(HTTP_NOAUTH)'.

Then, when I am injecting the HttpClient and don't want the AuthHttpInterceptor to be utilized, I specify '@Inject(HTTP_NOAUTH)'.


    @Injectable({
        providedIn: 'root',
    })
    export class SomeService {
        constructor(@Inject(HTTP_NOAUTH) private http: HttpClient) {
        ...

到目前为止,我发现(可能还有更多)的一个主要漏洞是,这是一个全有或全无的解决方案.它要么具有所有拦截器,要么不具有任何拦截器.可能有可能在Token提供的条目中注入单个拦截器,但我还没有深入研究.

The one major hole in this that I've found so far (and there may be more) is that it's an all or nothing solution. It either has all the Interceptors or it has none of them. It may be possible to inject individual Interceptors in the Token provided entry but I haven't dug far enough yet.

更新:

我现在可以如下选择针对HttpClient的每种配置要排除的拦截器.

I can now select which interceptors to exclude for each configuration of an HttpClient as follows.

import { Observable } from 'rxjs';
import { HttpHandler, HttpEvent, HttpRequest, HttpInterceptor, HttpBackend, HTTP_INTERCEPTORS, HttpClient } from '@angular/common/http';
import { Injector, InjectionToken } from '@angular/core';

export const provideTokenizedHttpClient = (token: InjectionToken<string>, options: { excludes: Function[] } = { excludes: [] }) => {
    return {
        provide: token,
        deps: [HttpBackend, Injector],
        useFactory: (backend: HttpBackend, injector: Injector) => {
            return new HttpClient(
                new HttpDynamicInterceptingHandler(backend, injector, options)
            );
        }
    }
}

class HttpInterceptorHandler implements HttpHandler {
    constructor(private next: HttpHandler, private interceptor: HttpInterceptor) { }
    handle(req: HttpRequest<any>): Observable<HttpEvent<any>> {
        return this.interceptor.intercept(req, this.next);
    }
}

class HttpDynamicInterceptingHandler implements HttpHandler {
    private chain: any = null;

    constructor(private backend: HttpBackend, private injector: Injector, private options: { excludes: Function[] } = { excludes: [] }) { }

    public handle(req: HttpRequest<any>): Observable<HttpEvent<any>> {
        if (this.chain === null) {
            const interceptors = this.injector.get(HTTP_INTERCEPTORS, [])
                .filter(entry => !this.options.excludes.includes(entry.constructor));

            this.chain = interceptors.reduceRight((next, interceptor) => {
                return new HttpInterceptorHandler(next, interceptor);
            }, this.backend);
        }
        return this.chain.handle(req);
    }
}

现在在我的提供程序中,我仅使用以下内容:

And now in my providers I simply use the following:

providers: [...
    provideTokenizedHttpClient(HTTP_NOAUTH, { excludes: [AuthHttpInterceptor] }),
    {
        provide: HTTP_INTERCEPTORS,
        useClass: AppBusyHttpInterceptor,
        multi: true
    },
    {
        provide: HTTP_INTERCEPTORS,
        useClass: AuthHttpInterceptor,
        multi: true
    }],

InjectionToken的创建及其在@Inject装饰器上的用法是相同的.

The creation of the InjectionToken and its usage on the @Inject decorator is the same.

这篇关于(可选)在角度4中应用HTTP拦截器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆