@@ -6,6 +6,8 @@ const util = require('./util')
6
6
const { InvalidArgumentError, ConnectTimeoutError } = require ( './errors' )
7
7
const timers = require ( '../util/timers' )
8
8
9
+ function noop ( ) { }
10
+
9
11
let tls // include tls conditionally since it is not always available
10
12
11
13
// TODO: session re-use does not wait for the first
@@ -96,6 +98,8 @@ function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, sess
96
98
97
99
const session = customSession || sessionCache . get ( sessionKey ) || null
98
100
101
+ port = port || 443
102
+
99
103
socket = tls . connect ( {
100
104
highWaterMark : 16384 , // TLS in node can't have bigger HWM anyway...
101
105
...options ,
@@ -105,7 +109,7 @@ function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, sess
105
109
// TODO(HTTP/2): Add support for h2c
106
110
ALPNProtocols : allowH2 ? [ 'http/1.1' , 'h2' ] : [ 'http/1.1' ] ,
107
111
socket : httpSocket , // upgrade socket connection
108
- port : port || 443 ,
112
+ port,
109
113
host : hostname
110
114
} )
111
115
@@ -116,11 +120,14 @@ function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, sess
116
120
} )
117
121
} else {
118
122
assert ( ! httpSocket , 'httpSocket can only be sent on TLS update' )
123
+
124
+ port = port || 80
125
+
119
126
socket = net . connect ( {
120
127
highWaterMark : 64 * 1024 , // Same as nodejs fs streams.
121
128
...options ,
122
129
localAddress,
123
- port : port || 80 ,
130
+ port,
124
131
host : hostname
125
132
} )
126
133
}
@@ -131,12 +138,12 @@ function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, sess
131
138
socket . setKeepAlive ( true , keepAliveInitialDelay )
132
139
}
133
140
134
- const cancelConnectTimeout = setupConnectTimeout ( new WeakRef ( socket ) , timeout )
141
+ const clearConnectTimeout = setupConnectTimeout ( new WeakRef ( socket ) , { timeout, hostname , port } )
135
142
136
143
socket
137
144
. setNoDelay ( true )
138
145
. once ( protocol === 'https:' ? 'secureConnect' : 'connect' , function ( ) {
139
- cancelConnectTimeout ( )
146
+ queueMicrotask ( clearConnectTimeout )
140
147
141
148
if ( callback ) {
142
149
const cb = callback
@@ -145,7 +152,7 @@ function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, sess
145
152
}
146
153
} )
147
154
. on ( 'error' , function ( err ) {
148
- cancelConnectTimeout ( )
155
+ queueMicrotask ( clearConnectTimeout )
149
156
150
157
if ( callback ) {
151
158
const cb = callback
@@ -158,50 +165,70 @@ function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, sess
158
165
}
159
166
}
160
167
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
+ */
161
176
const setupConnectTimeout = process . platform === 'win32'
162
- ? ( socket , timeout ) => {
163
- if ( ! timeout ) {
164
- return ( ) => { }
177
+ ? ( socketWeakRef , opts ) => {
178
+ if ( ! opts . timeout ) {
179
+ return noop
165
180
}
166
181
167
182
let s1 = null
168
183
let s2 = null
169
- const timer = timers . setTimeout ( ( ) => {
184
+ const fastTimer = timers . setFastTimeout ( ( ) => {
170
185
// setImmediate is added to make sure that we prioritize socket error events over timeouts
171
186
s1 = setImmediate ( ( ) => {
172
187
// 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 ) )
174
189
} )
175
- } , timeout )
190
+ } , opts . timeout )
176
191
return ( ) => {
177
- timers . clearTimeout ( timer )
192
+ timers . clearFastTimeout ( fastTimer )
178
193
clearImmediate ( s1 )
179
194
clearImmediate ( s2 )
180
195
}
181
196
}
182
- : ( socket , timeout ) => {
183
- if ( ! timeout ) {
184
- return ( ) => { }
197
+ : ( socketWeakRef , opts ) => {
198
+ if ( ! opts . timeout ) {
199
+ return noop
185
200
}
186
201
187
202
let s1 = null
188
- const timer = timers . setTimeout ( ( ) => {
203
+ const fastTimer = timers . setFastTimeout ( ( ) => {
189
204
// setImmediate is added to make sure that we prioritize socket error events over timeouts
190
205
s1 = setImmediate ( ( ) => {
191
- onConnectTimeout ( socket . deref ( ) )
206
+ onConnectTimeout ( socketWeakRef . deref ( ) , opts )
192
207
} )
193
- } , timeout )
208
+ } , opts . timeout )
194
209
return ( ) => {
195
- timers . clearTimeout ( timer )
210
+ timers . clearFastTimeout ( fastTimer )
196
211
clearImmediate ( s1 )
197
212
}
198
213
}
199
214
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 ) {
201
223
let message = 'Connect Timeout Error'
202
224
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 } ,`
204
228
}
229
+
230
+ message += ` timeout: ${ opts . timeout } ms)`
231
+
205
232
util . destroy ( socket , new ConnectTimeoutError ( message ) )
206
233
}
207
234
0 commit comments