@@ -589,92 +589,167 @@ export function createFetchPatch(params: ProxyAgentParams, originalFetch: typeof
589589 if ( ! proxyURL ) {
590590 const modifiedInit = {
591591 ...init ,
592- dispatcher : new undici . Agent ( {
593- allowH2,
594- connect : { ca : requestCA } ,
595- } )
592+ dispatcher : getAgent ( agentOptions . dispatcher , allowH2 , requestCA , addCerts ) ,
596593 } ;
597594 return originalFetch ( input , modifiedInit ) ;
598595 }
599596
600597 const state : Record < string , any > = { } ;
601- const proxyAuthorization = await params . lookupProxyAuthorization ?.( proxyURL , undefined , state ) ;
602598 const modifiedInit = {
603599 ...init ,
604- dispatcher : new undici . ProxyAgent ( {
605- uri : proxyURL ,
606- allowH2,
607- headers : proxyAuthorization ? { 'Proxy-Authorization' : proxyAuthorization } : undefined ,
608- requestTls : requestCA ? { allowH2, ca : requestCA } : { allowH2 } ,
609- proxyTls : proxyCA ? { allowH2, ca : proxyCA } : { allowH2 } ,
610- clientFactory : ( origin : URL , opts : object ) : undici . Dispatcher => ( new undici . Pool ( origin , opts ) as any ) . compose ( ( dispatch : undici . Dispatcher [ 'dispatch' ] ) => {
611- class ProxyAuthHandler extends undici . DecoratorHandler {
612- constructor ( private dispatch : undici . Dispatcher [ 'dispatch' ] , private options : undici . Dispatcher . DispatchOptions , private handler : undici . Dispatcher . DispatchHandler ) {
613- super ( handler ) ;
614- }
615- onResponseError ( controller : undici . Dispatcher . DispatchController , err : Error ) : void {
616- if ( ! ( err instanceof ProxyAuthError ) ) {
617- return this . handler . onResponseError ?.( controller , err ) ;
618- }
619- ( async ( ) => {
620- try {
621- const proxyAuthorization = await params . lookupProxyAuthorization ?.( proxyURL ! , err . proxyAuthenticate , state ) ;
622- if ( proxyAuthorization ) {
623- if ( ! this . options . headers ) {
624- this . options . headers = [ 'Proxy-Authorization' , proxyAuthorization ] ;
625- } else if ( Array . isArray ( this . options . headers ) ) {
626- const i = this . options . headers . findIndex ( ( value , index ) => index % 2 === 0 && value . toLowerCase ( ) === 'proxy-authorization' ) ;
627- if ( i === - 1 ) {
628- this . options . headers . push ( 'Proxy-Authorization' , proxyAuthorization ) ;
629- } else {
630- this . options . headers [ i + 1 ] = proxyAuthorization ;
631- }
632- } else if ( typeof ( this . options . headers as any ) [ Symbol . iterator ] === 'function' ) {
633- const headers = [ ...( this . options . headers as Iterable < [ string , string | string [ ] | undefined ] > ) ] ;
634- const i = headers . findIndex ( value => value [ 0 ] . toLowerCase ( ) === 'proxy-authorization' ) ;
635- if ( i === - 1 ) {
636- headers . push ( [ 'Proxy-Authorization' , proxyAuthorization ] ) ;
637- } else {
638- headers [ i ] [ 1 ] = proxyAuthorization ;
639- }
640- this . options . headers = headers ;
641- } else {
642- ( this . options . headers as Record < string , string | string [ ] | undefined > ) [ 'Proxy-Authorization' ] = proxyAuthorization ;
643- }
644- this . dispatch ( this . options , this ) ;
600+ dispatcher : await getProxyAgent ( params , agentOptions . dispatcher , proxyURL , allowH2 , requestCA , proxyCA , addCerts , state ) ,
601+ } ;
602+ return originalFetch ( input , modifiedInit ) ;
603+ } ;
604+ }
605+
606+ let previousAddCertsAgent : boolean | undefined = undefined ;
607+ let defaultAgent : undici . Agent | undefined = undefined ;
608+ let agentCache = new WeakMap < undici . Dispatcher , undici . Agent > ( ) ;
609+ function getAgent ( originalDispatcher : undici . Dispatcher | undefined , allowH2 : boolean | undefined , requestCA : string | Buffer | ( string | Buffer ) [ ] | undefined , currentAddCerts : boolean ) : undici . Agent | undefined {
610+ if ( previousAddCertsAgent !== currentAddCerts ) {
611+ previousAddCertsAgent = currentAddCerts ;
612+ defaultAgent = undefined ;
613+ agentCache = new WeakMap < undici . Dispatcher , undici . Agent > ( ) ;
614+ }
615+ if ( ! originalDispatcher ) {
616+ if ( ! defaultAgent ) {
617+ defaultAgent = createAgent ( allowH2 , requestCA ) ;
618+ }
619+ return defaultAgent ;
620+ }
621+
622+ if ( ! agentCache . has ( originalDispatcher ) ) {
623+ agentCache . set ( originalDispatcher , createAgent ( allowH2 , requestCA ) ) ;
624+ }
625+ return agentCache . get ( originalDispatcher ) ;
626+ }
627+
628+ function createAgent ( allowH2 : boolean | undefined , requestCA : string | Buffer | ( string | Buffer ) [ ] | undefined ) {
629+ return new undici . Agent ( {
630+ allowH2,
631+ connect : { ca : requestCA } ,
632+ } ) ;
633+ }
634+
635+ let previousAddCertsProxyAgent : boolean | undefined = undefined ;
636+ let defaultProxyAgent : undici . ProxyAgent | undefined = undefined ;
637+ let proxyAgentCache = new WeakMap < undici . Dispatcher , Map < string , undici . ProxyAgent > > ( ) ;
638+ async function getProxyAgent (
639+ params : ProxyAgentParams ,
640+ originalDispatcher : undici . Dispatcher | undefined ,
641+ proxyURL : string ,
642+ allowH2 : boolean | undefined ,
643+ requestCA : string | Buffer | ( string | Buffer ) [ ] | undefined ,
644+ proxyCA : string | Buffer | ( string | Buffer ) [ ] | undefined ,
645+ currentAddCerts : boolean ,
646+ state : Record < string , any >
647+ ) : Promise < undici . ProxyAgent > {
648+ if ( previousAddCertsProxyAgent !== currentAddCerts ) {
649+ previousAddCertsProxyAgent = currentAddCerts ;
650+ defaultProxyAgent = undefined ;
651+ proxyAgentCache = new WeakMap < undici . Dispatcher , Map < string , undici . ProxyAgent > > ( ) ;
652+ }
653+
654+ if ( ! originalDispatcher ) {
655+ if ( ! defaultProxyAgent ) {
656+ defaultProxyAgent = await createProxyAgent ( params , proxyURL , allowH2 , requestCA , proxyCA , state ) ;
657+ }
658+ return defaultProxyAgent ;
659+ }
660+
661+ let dispatcherCache = proxyAgentCache . get ( originalDispatcher ) ;
662+ if ( ! dispatcherCache ) {
663+ dispatcherCache = new Map < string , undici . ProxyAgent > ( ) ;
664+ proxyAgentCache . set ( originalDispatcher , dispatcherCache ) ;
665+ }
666+
667+ if ( ! dispatcherCache . has ( proxyURL ) ) {
668+ dispatcherCache . set ( proxyURL , await createProxyAgent ( params , proxyURL , allowH2 , requestCA , proxyCA , state ) ) ;
669+ }
670+ return dispatcherCache . get ( proxyURL ) ! ;
671+ }
672+
673+ async function createProxyAgent (
674+ params : ProxyAgentParams ,
675+ proxyURL : string ,
676+ allowH2 : boolean | undefined ,
677+ requestCA : string | Buffer | ( string | Buffer ) [ ] | undefined ,
678+ proxyCA : string | Buffer | ( string | Buffer ) [ ] | undefined ,
679+ state : Record < string , any >
680+ ) : Promise < undici . ProxyAgent > {
681+ const proxyAuthorization = await params . lookupProxyAuthorization ?.( proxyURL , undefined , state ) ;
682+ return new undici . ProxyAgent ( {
683+ uri : proxyURL ,
684+ allowH2,
685+ headers : proxyAuthorization ? { 'Proxy-Authorization' : proxyAuthorization } : undefined ,
686+ requestTls : requestCA ? { allowH2, ca : requestCA } : { allowH2 } ,
687+ proxyTls : proxyCA ? { allowH2, ca : proxyCA } : { allowH2 } ,
688+ clientFactory : ( origin : URL , opts : object ) : undici . Dispatcher => ( new undici . Pool ( origin , opts ) as any ) . compose ( ( dispatch : undici . Dispatcher [ 'dispatch' ] ) => {
689+ class ProxyAuthHandler extends undici . DecoratorHandler {
690+ constructor ( private dispatch : undici . Dispatcher [ 'dispatch' ] , private options : undici . Dispatcher . DispatchOptions , private handler : undici . Dispatcher . DispatchHandler ) {
691+ super ( handler ) ;
692+ }
693+ onResponseError ( controller : undici . Dispatcher . DispatchController , err : Error ) : void {
694+ if ( ! ( err instanceof ProxyAuthError ) ) {
695+ return this . handler . onResponseError ?.( controller , err ) ;
696+ }
697+ ( async ( ) => {
698+ try {
699+ const proxyAuthorization = await params . lookupProxyAuthorization ?.( proxyURL ! , err . proxyAuthenticate , state ) ;
700+ if ( proxyAuthorization ) {
701+ if ( ! this . options . headers ) {
702+ this . options . headers = [ 'Proxy-Authorization' , proxyAuthorization ] ;
703+ } else if ( Array . isArray ( this . options . headers ) ) {
704+ const i = this . options . headers . findIndex ( ( value , index ) => index % 2 === 0 && value . toLowerCase ( ) === 'proxy-authorization' ) ;
705+ if ( i === - 1 ) {
706+ this . options . headers . push ( 'Proxy-Authorization' , proxyAuthorization ) ;
645707 } else {
646- this . handler . onResponseError ?. ( controller , new undici . errors . RequestAbortedError ( `Proxy response (407) ?.== 200 when HTTP Tunneling` ) ) ; // Mimick undici's behavior
708+ this . options . headers [ i + 1 ] = proxyAuthorization ;
647709 }
648- } catch ( err : any ) {
649- this . handler . onResponseError ?.( controller , err ) ;
650- }
651- } ) ( ) ;
652- }
653- onRequestUpgrade ?( controller : undici . Dispatcher . DispatchController , statusCode : number , headers : IncomingHttpHeaders , socket : stream . Duplex ) : void {
654- if ( statusCode === 407 && headers ) {
655- let proxyAuthenticate : string | string [ ] | undefined ;
656- for ( const header in headers ) {
657- if ( header . toLowerCase ( ) === 'proxy-authenticate' ) {
658- proxyAuthenticate = headers [ header ] ;
659- break ;
710+ } else if ( typeof ( this . options . headers as any ) [ Symbol . iterator ] === 'function' ) {
711+ const headers = [ ...( this . options . headers as Iterable < [ string , string | string [ ] | undefined ] > ) ] ;
712+ const i = headers . findIndex ( value => value [ 0 ] . toLowerCase ( ) === 'proxy-authorization' ) ;
713+ if ( i === - 1 ) {
714+ headers . push ( [ 'Proxy-Authorization' , proxyAuthorization ] ) ;
715+ } else {
716+ headers [ i ] [ 1 ] = proxyAuthorization ;
660717 }
718+ this . options . headers = headers ;
719+ } else {
720+ ( this . options . headers as Record < string , string | string [ ] | undefined > ) [ 'Proxy-Authorization' ] = proxyAuthorization ;
661721 }
662- if ( proxyAuthenticate ) {
663- controller . abort ( new ProxyAuthError ( proxyAuthenticate ) ) ;
664- return ;
665- }
722+ this . dispatch ( this . options , this ) ;
723+ } else {
724+ this . handler . onResponseError ?.( controller , new undici . errors . RequestAbortedError ( `Proxy response (407) ?.== 200 when HTTP Tunneling` ) ) ; // Mimick undici's behavior
725+ }
726+ } catch ( err : any ) {
727+ this . handler . onResponseError ?.( controller , err ) ;
728+ }
729+ } ) ( ) ;
730+ }
731+ onRequestUpgrade ?( controller : undici . Dispatcher . DispatchController , statusCode : number , headers : IncomingHttpHeaders , socket : stream . Duplex ) : void {
732+ if ( statusCode === 407 && headers ) {
733+ let proxyAuthenticate : string | string [ ] | undefined ;
734+ for ( const header in headers ) {
735+ if ( header . toLowerCase ( ) === 'proxy-authenticate' ) {
736+ proxyAuthenticate = headers [ header ] ;
737+ break ;
666738 }
667- this . handler . onRequestUpgrade ?.( controller , statusCode , headers , socket ) ;
739+ }
740+ if ( proxyAuthenticate ) {
741+ controller . abort ( new ProxyAuthError ( proxyAuthenticate ) ) ;
742+ return ;
668743 }
669744 }
670- return function proxyAuthDispatch ( options : undici . Dispatcher . DispatchOptions , handler : undici . Dispatcher . DispatchHandler ) {
671- return dispatch ( options , new ProxyAuthHandler ( dispatch , options , handler ) ) ;
672- } ;
673- } ) ,
674- } )
675- } ;
676- return originalFetch ( input , modifiedInit ) ;
677- } ;
745+ this . handler . onRequestUpgrade ?. ( controller , statusCode , headers , socket ) ;
746+ }
747+ }
748+ return function proxyAuthDispatch ( options : undici . Dispatcher . DispatchOptions , handler : undici . Dispatcher . DispatchHandler ) {
749+ return dispatch ( options , new ProxyAuthHandler ( dispatch , options , handler ) ) ;
750+ } ;
751+ } ) ,
752+ } ) ;
678753}
679754
680755class ProxyAuthError extends Error {
@@ -752,7 +827,7 @@ function getAgentOptions(requestInit: RequestInit | undefined) {
752827 requestCA = originalProxyAgentOptions . requestTls && 'ca' in originalProxyAgentOptions . requestTls && originalProxyAgentOptions . requestTls . ca || undefined ;
753828 proxyCA = originalProxyAgentOptions . proxyTls && 'ca' in originalProxyAgentOptions . proxyTls && originalProxyAgentOptions . proxyTls . ca || undefined ;
754829 }
755- return { allowH2, requestCA, proxyCA, socketPath } ;
830+ return { dispatcher , allowH2, requestCA, proxyCA, socketPath } ;
756831}
757832
758833function addCertificatesToOptionsV1 ( params : ProxyAgentParams , addCertificatesV1 : boolean , opts : http . RequestOptions | tls . ConnectionOptions , callback : ( ) => void ) {
0 commit comments