@@ -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
1618let proxyState : ProxyState | null = null ;
19+ let isInitializing = false ;
20+ let isTearingDown = false ;
1721
1822export 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
4979export 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
71121export function getCurrentProxyUrl ( ) : string | null {
0 commit comments