@@ -6,6 +6,8 @@ const util = require('./util')
66const { InvalidArgumentError, ConnectTimeoutError } = require ( './errors' )
77const timers = require ( '../util/timers' )
88
9+ function noop ( ) { }
10+
911let tls // include tls conditionally since it is not always available
1012
1113// TODO: session re-use does not wait for the first
@@ -96,6 +98,8 @@ function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, sess
9698
9799 const session = customSession || sessionCache . get ( sessionKey ) || null
98100
101+ port = port || 443
102+
99103 socket = tls . connect ( {
100104 highWaterMark : 16384 , // TLS in node can't have bigger HWM anyway...
101105 ...options ,
@@ -105,7 +109,7 @@ function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, sess
105109 // TODO(HTTP/2): Add support for h2c
106110 ALPNProtocols : allowH2 ? [ 'http/1.1' , 'h2' ] : [ 'http/1.1' ] ,
107111 socket : httpSocket , // upgrade socket connection
108- port : port || 443 ,
112+ port,
109113 host : hostname
110114 } )
111115
@@ -116,11 +120,14 @@ function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, sess
116120 } )
117121 } else {
118122 assert ( ! httpSocket , 'httpSocket can only be sent on TLS update' )
123+
124+ port = port || 80
125+
119126 socket = net . connect ( {
120127 highWaterMark : 64 * 1024 , // Same as nodejs fs streams.
121128 ...options ,
122129 localAddress,
123- port : port || 80 ,
130+ port,
124131 host : hostname
125132 } )
126133 }
@@ -131,12 +138,12 @@ function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, sess
131138 socket . setKeepAlive ( true , keepAliveInitialDelay )
132139 }
133140
134- const cancelConnectTimeout = setupConnectTimeout ( new WeakRef ( socket ) , timeout )
141+ const clearConnectTimeout = setupConnectTimeout ( new WeakRef ( socket ) , { timeout, hostname , port } )
135142
136143 socket
137144 . setNoDelay ( true )
138145 . once ( protocol === 'https:' ? 'secureConnect' : 'connect' , function ( ) {
139- cancelConnectTimeout ( )
146+ queueMicrotask ( clearConnectTimeout )
140147
141148 if ( callback ) {
142149 const cb = callback
@@ -145,7 +152,7 @@ function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, sess
145152 }
146153 } )
147154 . on ( 'error' , function ( err ) {
148- cancelConnectTimeout ( )
155+ queueMicrotask ( clearConnectTimeout )
149156
150157 if ( callback ) {
151158 const cb = callback
@@ -158,50 +165,70 @@ function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, sess
158165 }
159166}
160167
168+ /**
169+ * @param {WeakRef<net.Socket> } socketWeakRef
170+ * @param {object } opts
171+ * @param {number } opts.timeout
172+ * @param {string } opts.hostname
173+ * @param {number } opts.port
174+ * @returns {() => void }
175+ */
161176const setupConnectTimeout = process . platform === 'win32'
162- ? ( socket , timeout ) => {
163- if ( ! timeout ) {
164- return ( ) => { }
177+ ? ( socketWeakRef , opts ) => {
178+ if ( ! opts . timeout ) {
179+ return noop
165180 }
166181
167182 let s1 = null
168183 let s2 = null
169- const timer = timers . setTimeout ( ( ) => {
184+ const fastTimer = timers . setFastTimeout ( ( ) => {
170185 // setImmediate is added to make sure that we prioritize socket error events over timeouts
171186 s1 = setImmediate ( ( ) => {
172187 // Windows needs an extra setImmediate probably due to implementation differences in the socket logic
173- s2 = setImmediate ( ( ) => onConnectTimeout ( socket . deref ( ) ) )
188+ s2 = setImmediate ( ( ) => onConnectTimeout ( socketWeakRef . deref ( ) , opts ) )
174189 } )
175- } , timeout )
190+ } , opts . timeout )
176191 return ( ) => {
177- timers . clearTimeout ( timer )
192+ timers . clearFastTimeout ( fastTimer )
178193 clearImmediate ( s1 )
179194 clearImmediate ( s2 )
180195 }
181196 }
182- : ( socket , timeout ) => {
183- if ( ! timeout ) {
184- return ( ) => { }
197+ : ( socketWeakRef , opts ) => {
198+ if ( ! opts . timeout ) {
199+ return noop
185200 }
186201
187202 let s1 = null
188- const timer = timers . setTimeout ( ( ) => {
203+ const fastTimer = timers . setFastTimeout ( ( ) => {
189204 // setImmediate is added to make sure that we prioritize socket error events over timeouts
190205 s1 = setImmediate ( ( ) => {
191- onConnectTimeout ( socket . deref ( ) )
206+ onConnectTimeout ( socketWeakRef . deref ( ) , opts )
192207 } )
193- } , timeout )
208+ } , opts . timeout )
194209 return ( ) => {
195- timers . clearTimeout ( timer )
210+ timers . clearFastTimeout ( fastTimer )
196211 clearImmediate ( s1 )
197212 }
198213 }
199214
200- function onConnectTimeout ( socket ) {
215+ /**
216+ * @param {net.Socket } socket
217+ * @param {object } opts
218+ * @param {number } opts.timeout
219+ * @param {string } opts.hostname
220+ * @param {number } opts.port
221+ */
222+ function onConnectTimeout ( socket , opts ) {
201223 let message = 'Connect Timeout Error'
202224 if ( Array . isArray ( socket . autoSelectFamilyAttemptedAddresses ) ) {
203- message += ` (attempted addresses: ${ socket . autoSelectFamilyAttemptedAddresses . join ( ', ' ) } )`
225+ message += ` (attempted addresses: ${ socket . autoSelectFamilyAttemptedAddresses . join ( ', ' ) } ,`
226+ } else {
227+ message += ` (attempted address: ${ opts . hostname } :${ opts . port } ,`
204228 }
229+
230+ message += ` timeout: ${ opts . timeout } ms)`
231+
205232 util . destroy ( socket , new ConnectTimeoutError ( message ) )
206233}
207234
0 commit comments