HttpModule
来执行 HTTP 请求。
在我的一项服务中,我向第三方应用程序发送请求,该应用程序每秒最多允许 3 个请求。因此,我想给这个服务使用的axios实例添加一个请求拦截器。由于 Nest 中的模块是单例,因此它们共享相同的提供程序实例,因此共享 HttpService
的相同 Axios 实例。因此,如果我修改我的提供者之一中注入的 HttpService
的 Axios 实例,例如添加一个请求拦截器 (httpService.axiosRef.interceptors.request.use(...)
),从我的应用程序中的 any 服务发送的每个使用注入的 HttpService
的请求都将被拦截。
应用程序的示例模块结构:
// app.module.ts
@Module({
imports: [
ExternalIntegrationAPIModule,
ExternalManagementAPIModule
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
// externalIntegrationAPI.module.ts
@Module({
imports: [HttpModule],
exports: [ExternalIntegrationAPIConnector],
providers: [ExternalIntegrationAPIConnector],
})
export class ExternalIntegrationAPIModule {}
// externalIntegrationAPI.connector.ts
@Injectable()
export class ExternalIntegrationAPIConnector {
constructor(
private httpService: HttpService,
) {...}
// ...methods that use httpService to perform requests
}
// externalManagementAPI.module.ts
@Module({
imports: [HttpModule],
exports: [ExternalManagementAPIConnector],
providers: [ExternalManagementAPIConnector],
})
export class ExternalManagementAPIModule {}
// externalManagementAPI.connector.ts
@Injectable()
export class ExternalManagementAPIConnector {
constructor(
private httpService: HttpService,
) {
// this.httpService.axiosRef.interceptors.request.use(...);
// Since both, ExternalManagementAPIConnector and ExternalIntegrationAPIConnector
// share the same Axios instance this would also intercept requests made from
// ExternalIntegrationAPIConnector
}
// ...methods that use httpService to perform requests
}
在这种情况下,我想拦截从
ExternalManagementAPIConnector
发出的请求,以确保每秒 3 个请求的限制,同时避免拦截从 ExternalIntegrationAPIConnector
执行的任何请求。
如何添加拦截器,以便仅拦截在所需服务中执行的请求?
我尝试使用
register
的HttpModule
功能来创建一个独立的Axios实例。此外,我尝试创建自己的 HttpModule
和 HttpService
扩展来创建独立的 Axios 实例。只要我只导入这个新模块一次,就可以了。导入此模块的每个其他模块将再次共享相同的 Axios 实例,类似于原始的行为 HttpModule
更新:
我尝试使用此处提出的解决方案:NestJS:每个模块导入的 HttpModule 的新实例。
然而,一开始这也拦截了来自
TerminusModule
的健康 ping。这可以通过在我的健康服务中注入 HttpService
并将注入的 HttpService 作为配置传递来解决:
@Injectable()
class HealthService {
constructor(
private readonly healthCheckService: HealthCheckService,
private readonly httpHealthIndicator: HttpHealthIndicator,
private readonly httpService: HttpService,
...
) {...}
async checkHealth() {
const healthCheck = await this.healthCheckService.check([
() => this.httpHealthIndicator.pingCheck(
'targetKeyName',
{ httpClient: this.httpService }
),
...
]);
}
}
由于在导入中使用空配置对象调用
register()
方法来创建 HttpModule
的单独实例似乎是一个 hacky 解决方案,我仍然很好奇是否还有其他干净的方法来解决我的问题。
为 HTTP 服务定义自定义提供程序并在提供程序中配置拦截器怎么样?
// externalManagementAPI.module.ts
import { HttpModule, HttpService, Module } from '@nestjs/common';
import { AxiosRequestConfig } from 'axios';
@Module({
imports: [HttpModule],
exports: [ExternalManagementAPIConnector],
providers: [
ExternalManagementAPIConnector,
{
provide: 'HttpServiceWithInterceptor',
useFactory: (httpService: HttpService) => {
const axiosInstance = httpService.axiosRef;
axiosInstance.interceptors.request.use((config:
AxiosRequestConfig) => {
// interceptor logic
// You can modify the request config or perform
return config;
});
return axiosInstance;
},
inject: [HttpService],
},
],
})
export class ExternalManagementAPIModule {}
// externalManagementAPI.connector.ts
import { HttpService, Inject, Injectable } from '@nestjs/common';
import { AxiosInstance } from 'axios';
@Injectable()
export class ExternalManagementAPIConnector {
constructor(
@Inject('HttpServiceWithInterceptor')
private httpService: AxiosInstance,
) {
// You can use this.httpService to make requests with the
interceptor applied
}
// methods that use httpService to perform requests
}