Skip to content

Commit 5fcb453

Browse files
committed
Enhance proxy agent initialization and teardown logic to prevent concurrent calls and improve resource management
1 parent 7490faf commit 5fcb453

File tree

1 file changed

+84
-34
lines changed

1 file changed

+84
-34
lines changed

packages/main/src/backend/proxyConfig/agentManager.ts

Lines changed: 84 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -11,61 +11,111 @@ interface ProxyState {
1111
originalHttpAgent: HttpAgent;
1212
originalHttpsAgent: HttpsAgent;
1313
proxyAgent: ProxyAgent;
14+
originalHttpProxy: string | undefined;
15+
originalHttpsProxy: string | undefined;
1416
}
1517

1618
let proxyState: ProxyState | null = null;
19+
let isInitializing = false;
20+
let isTearingDown = false;
1721

1822
export function initializeProxyAgents(proxyUrl: string): void {
19-
if (proxyState?.proxyUrl === proxyUrl) {
20-
logger.log(`Proxy already initialized with ${proxyUrl}`);
23+
if (isInitializing) {
24+
logger.log('Proxy initialization already in progress, ignoring concurrent call');
2125
return;
2226
}
2327

24-
logger.log(`Initializing proxy agents with ${proxyUrl}`);
25-
26-
// Set environment variables for @puppeteer/browsers
27-
process.env.HTTP_PROXY = proxyUrl;
28-
process.env.HTTPS_PROXY = proxyUrl;
29-
30-
// Store original agents and create proxy agent
31-
const proxyAgent = new ProxyAgent({ getProxyForUrl: () => proxyUrl });
32-
33-
proxyState = {
34-
proxyUrl,
35-
originalHttpAgent: http.globalAgent,
36-
originalHttpsAgent: https.globalAgent,
37-
proxyAgent,
38-
};
28+
if (isTearingDown) {
29+
throw new Error('Cannot initialize proxy while teardown is in progress');
30+
}
3931

40-
// Set proxy agents globally
41-
http.globalAgent = proxyAgent;
42-
https.globalAgent = proxyAgent;
32+
if (proxyState?.proxyUrl === proxyUrl) {
33+
logger.log(`Proxy already initialized with ${proxyUrl}`);
34+
return;
35+
}
4336

44-
// Configure undici for fetch() API
45-
const undiciProxyAgent = new UndiciProxyAgent(proxyUrl);
46-
setGlobalDispatcher(undiciProxyAgent);
37+
isInitializing = true;
38+
39+
try {
40+
// Clean up previous proxy before setting up a new one to avoid resource leaks
41+
if (proxyState) {
42+
tearDownProxyAgents();
43+
}
44+
45+
logger.log(`Initializing proxy agents with ${proxyUrl}`);
46+
47+
// Store original environment variables so they can be restored later
48+
const originalHttpProxy = process.env.HTTP_PROXY;
49+
const originalHttpsProxy = process.env.HTTPS_PROXY;
50+
51+
// Set environment variables for @puppeteer/browsers
52+
process.env.HTTP_PROXY = proxyUrl;
53+
process.env.HTTPS_PROXY = proxyUrl;
54+
55+
// Store original agents and create proxy agent
56+
const proxyAgent = new ProxyAgent({ getProxyForUrl: () => proxyUrl });
57+
58+
proxyState = {
59+
proxyUrl,
60+
originalHttpAgent: http.globalAgent,
61+
originalHttpsAgent: https.globalAgent,
62+
proxyAgent,
63+
originalHttpProxy,
64+
originalHttpsProxy,
65+
};
66+
67+
// Set proxy agents globally
68+
http.globalAgent = proxyAgent;
69+
https.globalAgent = proxyAgent;
70+
71+
// Configure undici for fetch() API
72+
const undiciProxyAgent = new UndiciProxyAgent(proxyUrl);
73+
setGlobalDispatcher(undiciProxyAgent);
74+
} finally {
75+
isInitializing = false;
76+
}
4777
}
4878

4979
export function tearDownProxyAgents(): void {
80+
if (isTearingDown) {
81+
logger.log('Proxy teardown already in progress, ignoring concurrent call');
82+
return;
83+
}
84+
5085
if (!proxyState) {
5186
return;
5287
}
5388

54-
logger.log('Tearing down proxy agents');
89+
isTearingDown = true;
90+
91+
try {
92+
logger.log('Tearing down proxy agents');
5593

56-
// Restore original agents
57-
http.globalAgent = proxyState.originalHttpAgent;
58-
https.globalAgent = proxyState.originalHttpsAgent;
94+
// Restore original agents
95+
http.globalAgent = proxyState.originalHttpAgent;
96+
https.globalAgent = proxyState.originalHttpsAgent;
5997

60-
// Clear environment variables
61-
delete process.env.HTTP_PROXY;
62-
delete process.env.HTTPS_PROXY;
98+
// Restore original environment variables instead of deleting them
99+
if (proxyState.originalHttpProxy !== undefined) {
100+
process.env.HTTP_PROXY = proxyState.originalHttpProxy;
101+
} else {
102+
delete process.env.HTTP_PROXY;
103+
}
63104

64-
// Reset undici dispatcher to default
65-
setGlobalDispatcher(new UndiciAgent());
105+
if (proxyState.originalHttpsProxy !== undefined) {
106+
process.env.HTTPS_PROXY = proxyState.originalHttpsProxy;
107+
} else {
108+
delete process.env.HTTPS_PROXY;
109+
}
66110

67-
// Clear state
68-
proxyState = null;
111+
// Reset undici dispatcher to default
112+
setGlobalDispatcher(new UndiciAgent());
113+
114+
// Clear state
115+
proxyState = null;
116+
} finally {
117+
isTearingDown = false;
118+
}
69119
}
70120

71121
export function getCurrentProxyUrl(): string | null {

0 commit comments

Comments
 (0)