@@ -27,7 +27,9 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
2727} ;
2828Object . defineProperty ( exports , "__esModule" , { value : true } ) ;
2929exports . Agent = void 0 ;
30+ const net = __importStar ( require ( "net" ) ) ;
3031const http = __importStar ( require ( "http" ) ) ;
32+ const https_1 = require ( "https" ) ;
3133__exportStar ( require ( "./helpers" ) , exports ) ;
3234const INTERNAL = Symbol ( 'AgentBaseInternalState' ) ;
3335class Agent extends http . Agent {
@@ -64,22 +66,83 @@ class Agent extends http.Agent {
6466 . some ( ( l ) => l . indexOf ( '(https.js:' ) !== - 1 ||
6567 l . indexOf ( 'node:https:' ) !== - 1 ) ;
6668 }
69+ // In order to support async signatures in `connect()` and Node's native
70+ // connection pooling in `http.Agent`, the array of sockets for each origin
71+ // has to be updated synchronously. This is so the length of the array is
72+ // accurate when `addRequest()` is next called. We achieve this by creating a
73+ // fake socket and adding it to `sockets[origin]` and incrementing
74+ // `totalSocketCount`.
75+ incrementSockets ( name ) {
76+ // If `maxSockets` and `maxTotalSockets` are both Infinity then there is no
77+ // need to create a fake socket because Node.js native connection pooling
78+ // will never be invoked.
79+ if ( this . maxSockets === Infinity && this . maxTotalSockets === Infinity ) {
80+ return null ;
81+ }
82+ // All instances of `sockets` are expected TypeScript errors. The
83+ // alternative is to add it as a private property of this class but that
84+ // will break TypeScript subclassing.
85+ if ( ! this . sockets [ name ] ) {
86+ // @ts -expect-error `sockets` is readonly in `@types/node`
87+ this . sockets [ name ] = [ ] ;
88+ }
89+ const fakeSocket = new net . Socket ( { writable : false } ) ;
90+ this . sockets [ name ] . push ( fakeSocket ) ;
91+ // @ts -expect-error `totalSocketCount` isn't defined in `@types/node`
92+ this . totalSocketCount ++ ;
93+ return fakeSocket ;
94+ }
95+ decrementSockets ( name , socket ) {
96+ if ( ! this . sockets [ name ] || socket === null ) {
97+ return ;
98+ }
99+ const sockets = this . sockets [ name ] ;
100+ const index = sockets . indexOf ( socket ) ;
101+ if ( index !== - 1 ) {
102+ sockets . splice ( index , 1 ) ;
103+ // @ts -expect-error `totalSocketCount` isn't defined in `@types/node`
104+ this . totalSocketCount -- ;
105+ if ( sockets . length === 0 ) {
106+ // @ts -expect-error `sockets` is readonly in `@types/node`
107+ delete this . sockets [ name ] ;
108+ }
109+ }
110+ }
111+ // In order to properly update the socket pool, we need to call `getName()` on
112+ // the core `https.Agent` if it is a secureEndpoint.
113+ getName ( options ) {
114+ const secureEndpoint = typeof options . secureEndpoint === 'boolean'
115+ ? options . secureEndpoint
116+ : this . isSecureEndpoint ( options ) ;
117+ if ( secureEndpoint ) {
118+ // @ts -expect-error `getName()` isn't defined in `@types/node`
119+ return https_1 . Agent . prototype . getName . call ( this , options ) ;
120+ }
121+ // @ts -expect-error `getName()` isn't defined in `@types/node`
122+ return super . getName ( options ) ;
123+ }
67124 createSocket ( req , options , cb ) {
68125 const connectOpts = {
69126 ...options ,
70127 secureEndpoint : this . isSecureEndpoint ( options ) ,
71128 } ;
129+ const name = this . getName ( connectOpts ) ;
130+ const fakeSocket = this . incrementSockets ( name ) ;
72131 Promise . resolve ( )
73132 . then ( ( ) => this . connect ( req , connectOpts ) )
74133 . then ( ( socket ) => {
134+ this . decrementSockets ( name , fakeSocket ) ;
75135 if ( socket instanceof http . Agent ) {
76136 // @ts -expect-error `addRequest()` isn't defined in `@types/node`
77137 return socket . addRequest ( req , connectOpts ) ;
78138 }
79139 this [ INTERNAL ] . currentSocket = socket ;
80140 // @ts -expect-error `createSocket()` isn't defined in `@types/node`
81141 super . createSocket ( req , options , cb ) ;
82- } , cb ) ;
142+ } , ( err ) => {
143+ this . decrementSockets ( name , fakeSocket ) ;
144+ cb ( err ) ;
145+ } ) ;
83146 }
84147 createConnection ( ) {
85148 const socket = this [ INTERNAL ] . currentSocket ;
0 commit comments