Angular:在库模块中声明的HttpInterceptor拦截库外的请求



我在Angular中遇到了一个问题,即在Angular库中声明的HttpInterceptors的实现实例正在拦截库外(即消费应用程序(对HttpClient调用的请求。

我很难理解为什么会发生这种事。

HTTP_INTERCEPTOR注入是在我的库的模块声明上配置的,而不是我的应用程序。

我的设置如下:

我有如下声明的ng-mfe库模块:

import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http';
import { ModuleWithProviders, NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ConfigToken } from './tokens';
import { AuthHttpClient } from './services/auth/auth-http.service';
import { Config } from './models/module.model';
import { NgSelectModule } from '@ng-select/ng-select';
import { TokenInterceptor } from './services/auth/token.interceptor';
const components = [/* components */];
const imports = [CommonModule, HttpClientModule, NgSelectModule, FormsModule, ReactiveFormsModule];
@NgModule({
declarations: [...components],
imports: [...imports],
exports: [...components],
providers: [],
})
export class NGMfeModule {
static forRoot(config: Config): ModuleWithProviders<NGMfeModule> {
return {
ngModule: NGMfeModule,
providers: [
AuthHttpClient,
TokenInterceptor,
{
provide: ConfigToken,
useValue: config,
},
{
provide: HTTP_INTERCEPTORS,
useClass: TokenInterceptor,
multi: true,
},
],
};
}
}

该库处理对API的HTTP请求,并附加与所述API通信所需的相关auth头。

我已经实现了HttpInterceptor(TokenInterceptor(并提供了HTTP_INTERCEPTORS注入令牌。

import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Inject, Injectable } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { filter, map, switchMap } from 'rxjs/operators';
import { selectAccessToken } '../../state/shared-config/shared-config.selectors';
@Injectable()
export class TokenInterceptor implements HttpInterceptor {
constructor(private store: Store) {}
/**
* Intercept all HTTP requests and add the required auth headers to them
*
* @param req The request to intercept
* @param next Transform HttpRequests into a stream
*/
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return this.store.select(selectAccessToken).pipe(
filter((data) => !!data),
switchMap((data) => {
req = req.clone({
setHeaders: {
Authorization: `Bearer ${data}`,
},
});
return next.handle(req);
})
);
}
}

最后,我的AuthHttpClient:

import { HttpClient } from '@angular/common/http';
import { HttpOptions } from '../../models/http.model';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
@Injectable()
export class AuthHttpClient {
constructor(private http: HttpClient) {}
get(url: string, options?: HttpOptions): Observable<Object> {
return this.http.get(url, options);
}
}

这是库配置,我的Angular应用程序在库外的模块是如下所示:

import { NGMfeModule } from 'ng-mfe';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { NgModule } from '@angular/core';
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule,
NGMfeModule.forRoot(/* config */),
],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}

最后,在AppComponent类中,我注入了两个服务,一个是我的AuthHttpClient,另一个是Angular的HttpClient:

import { Component, OnInit } from '@angular/core';
import { AuthHttpClient, getAccessToken } from 'ng-mfe';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent implements OnInit {
constructor(
private http1: AuthHttpClient,
private http2: HttpClient
) {}
ngOnInit() {
this.http1.get('test-url-1').subscribe();
this.http2.get('test-url-2').subscribe();
}
}

我希望http1发出的调用被截获,因为它是ng-mfe中声明的AuthHttpClient的实例,但http2是Angular的HttpClient-的实例,HttpClientModuleAppModule中导入。

也许我对Angular的singleton的理解是错误的——但为什么来自http2的请求会被拦截?我的设置是否错误(有没有办法正确配置我的模块,这样就不会发生这种情况(?或者这是正确的、标准的行为吗?

我以前在AuthHttpClientTokenInterceptor服务中有Injectable({ providedIn: 'root' }),但没有在NGMfeModuleproviders数组中声明它们,但删除了它们,因此它们在本地声明。但这并没有产生任何影响。这是正确的吗,还是应该始终为providedIn: root

谢谢你的帮助!

您的问题有两种解决方案:

  1. 您可以提供自己的HttpClient实现并注入您的HTTP拦截器,如下所示:https://indepth.dev/posts/1455/how-to-split-http-interceptors-between-multiple-backends

  2. 有了Angular 12,现在就有了HttpContextTokens。有了这些你可以基于请求中特定令牌的存在:https://netbasal.com/new-in-angular-v12-passing-context-to-http-interceptors-308a1ca2f3dd

相关内容

  • 没有找到相关文章

最新更新