Browse Source

fix(api): use global undici dispatcher for HTTP_PROXY across all data providers

Switch to setGlobalDispatcher(new EnvHttpProxyAgent()) at bootstrap so every
service that uses native fetch picks up HTTP_PROXY / HTTPS_PROXY / NO_PROXY
without per-call wiring.

Reverts the inline ProxyAgent in manual.service.ts because the global
dispatcher covers it (and the other 7 services that hit native fetch:
coingecko, openfigi, trackinsight, eod-historical-data,
financial-modeling-prep, ghostfolio, rapid-api). Also gets NO_PROXY
handling for free, which the inline ProxyAgent path did not have.

Matches the approach @dtslvr suggested in #6206.
pull/6581/head
Matt Van Horn 2 weeks ago
parent
commit
f961ab3502
Failed to extract signature
  1. 6
      apps/api/src/main.ts
  2. 17
      apps/api/src/services/data-provider/manual/manual.service.ts

6
apps/api/src/main.ts

@ -18,10 +18,16 @@ import type { NestExpressApplication } from '@nestjs/platform-express';
import cookieParser from 'cookie-parser'; import cookieParser from 'cookie-parser';
import { NextFunction, Request, Response } from 'express'; import { NextFunction, Request, Response } from 'express';
import helmet from 'helmet'; import helmet from 'helmet';
import { EnvHttpProxyAgent, setGlobalDispatcher } from 'undici';
import { AppModule } from './app/app.module'; import { AppModule } from './app/app.module';
import { environment } from './environments/environment'; import { environment } from './environments/environment';
// Route Node's global `fetch` (used by all data-provider services) through
// HTTP_PROXY / HTTPS_PROXY when those env vars are set. Native fetch
// otherwise ignores them. EnvHttpProxyAgent reads NO_PROXY natively.
setGlobalDispatcher(new EnvHttpProxyAgent());
async function bootstrap() { async function bootstrap() {
const configApp = await NestFactory.create(AppModule); const configApp = await NestFactory.create(AppModule);
const configService = configApp.get<ConfigService>(ConfigService); const configService = configApp.get<ConfigService>(ConfigService);

17
apps/api/src/services/data-provider/manual/manual.service.ts

@ -27,7 +27,6 @@ import { Injectable, Logger } from '@nestjs/common';
import { DataSource, SymbolProfile } from '@prisma/client'; import { DataSource, SymbolProfile } from '@prisma/client';
import * as cheerio from 'cheerio'; import * as cheerio from 'cheerio';
import { addDays, format, isBefore } from 'date-fns'; import { addDays, format, isBefore } from 'date-fns';
import { ProxyAgent } from 'undici';
@Injectable() @Injectable()
export class ManualService implements DataProviderInterface { export class ManualService implements DataProviderInterface {
@ -293,24 +292,12 @@ export class ManualService implements DataProviderInterface {
}): Promise<number> { }): Promise<number> {
let locale = scraperConfiguration.locale; let locale = scraperConfiguration.locale;
const fetchOptions: RequestInit & { dispatcher?: ProxyAgent } = { const response = await fetch(scraperConfiguration.url, {
headers: scraperConfiguration.headers as HeadersInit, headers: scraperConfiguration.headers as HeadersInit,
signal: AbortSignal.timeout( signal: AbortSignal.timeout(
this.configurationService.get('REQUEST_TIMEOUT') this.configurationService.get('REQUEST_TIMEOUT')
) )
}; });
const proxyUrl =
process.env.HTTPS_PROXY ??
process.env.https_proxy ??
process.env.HTTP_PROXY ??
process.env.http_proxy;
if (proxyUrl) {
fetchOptions.dispatcher = new ProxyAgent(proxyUrl);
}
const response = await fetch(scraperConfiguration.url, fetchOptions);
if (!response.ok) { if (!response.ok) {
throw new Error( throw new Error(

Loading…
Cancel
Save