aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/node_modules/undici/lib/core/connect.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/undici/lib/core/connect.js')
-rw-r--r--node_modules/undici/lib/core/connect.js119
1 files changed, 85 insertions, 34 deletions
diff --git a/node_modules/undici/lib/core/connect.js b/node_modules/undici/lib/core/connect.js
index 3309117..8cd8abc 100644
--- a/node_modules/undici/lib/core/connect.js
+++ b/node_modules/undici/lib/core/connect.js
@@ -1,9 +1,12 @@
'use strict'
-const net = require('net')
-const assert = require('assert')
+const net = require('node:net')
+const assert = require('node:assert')
const util = require('./util')
const { InvalidArgumentError, ConnectTimeoutError } = require('./errors')
+const timers = require('../util/timers')
+
+function noop () {}
let tls // include tls conditionally since it is not always available
@@ -15,7 +18,7 @@ let tls // include tls conditionally since it is not always available
let SessionCache
// FIXME: remove workaround when the Node bug is fixed
// https://github.com/nodejs/node/issues/49344#issuecomment-1741776308
-if (global.FinalizationRegistry && !process.env.NODE_V8_COVERAGE) {
+if (global.FinalizationRegistry && !(process.env.NODE_V8_COVERAGE || process.env.UNDICI_NO_FG)) {
SessionCache = class WeakSessionCache {
constructor (maxCachedSessions) {
this._maxCachedSessions = maxCachedSessions
@@ -73,7 +76,7 @@ if (global.FinalizationRegistry && !process.env.NODE_V8_COVERAGE) {
}
}
-function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, ...opts }) {
+function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, session: customSession, ...opts }) {
if (maxCachedSessions != null && (!Number.isInteger(maxCachedSessions) || maxCachedSessions < 0)) {
throw new InvalidArgumentError('maxCachedSessions must be a positive integer or zero')
}
@@ -86,15 +89,17 @@ function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, ...o
let socket
if (protocol === 'https:') {
if (!tls) {
- tls = require('tls')
+ tls = require('node:tls')
}
servername = servername || options.servername || util.getServerName(host) || null
const sessionKey = servername || hostname
- const session = sessionCache.get(sessionKey) || null
-
assert(sessionKey)
+ const session = customSession || sessionCache.get(sessionKey) || null
+
+ port = port || 443
+
socket = tls.connect({
highWaterMark: 16384, // TLS in node can't have bigger HWM anyway...
...options,
@@ -104,7 +109,7 @@ function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, ...o
// TODO(HTTP/2): Add support for h2c
ALPNProtocols: allowH2 ? ['http/1.1', 'h2'] : ['http/1.1'],
socket: httpSocket, // upgrade socket connection
- port: port || 443,
+ port,
host: hostname
})
@@ -115,11 +120,14 @@ function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, ...o
})
} else {
assert(!httpSocket, 'httpSocket can only be sent on TLS update')
+
+ port = port || 80
+
socket = net.connect({
highWaterMark: 64 * 1024, // Same as nodejs fs streams.
...options,
localAddress,
- port: port || 80,
+ port,
host: hostname
})
}
@@ -130,12 +138,12 @@ function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, ...o
socket.setKeepAlive(true, keepAliveInitialDelay)
}
- const cancelTimeout = setupTimeout(() => onConnectTimeout(socket), timeout)
+ const clearConnectTimeout = setupConnectTimeout(new WeakRef(socket), { timeout, hostname, port })
socket
.setNoDelay(true)
.once(protocol === 'https:' ? 'secureConnect' : 'connect', function () {
- cancelTimeout()
+ queueMicrotask(clearConnectTimeout)
if (callback) {
const cb = callback
@@ -144,7 +152,7 @@ function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, ...o
}
})
.on('error', function (err) {
- cancelTimeout()
+ queueMicrotask(clearConnectTimeout)
if (callback) {
const cb = callback
@@ -157,33 +165,76 @@ function buildConnector ({ allowH2, maxCachedSessions, socketPath, timeout, ...o
}
}
-function setupTimeout (onConnectTimeout, timeout) {
- if (!timeout) {
- return () => {}
- }
+/**
+ * @param {WeakRef<net.Socket>} socketWeakRef
+ * @param {object} opts
+ * @param {number} opts.timeout
+ * @param {string} opts.hostname
+ * @param {number} opts.port
+ * @returns {() => void}
+ */
+const setupConnectTimeout = process.platform === 'win32'
+ ? (socketWeakRef, opts) => {
+ if (!opts.timeout) {
+ return noop
+ }
- let s1 = null
- let s2 = null
- const timeoutId = setTimeout(() => {
- // setImmediate is added to make sure that we priotorise socket error events over timeouts
- s1 = setImmediate(() => {
- if (process.platform === 'win32') {
+ let s1 = null
+ let s2 = null
+ const fastTimer = timers.setFastTimeout(() => {
+ // setImmediate is added to make sure that we prioritize socket error events over timeouts
+ s1 = setImmediate(() => {
// Windows needs an extra setImmediate probably due to implementation differences in the socket logic
- s2 = setImmediate(() => onConnectTimeout())
- } else {
- onConnectTimeout()
+ s2 = setImmediate(() => onConnectTimeout(socketWeakRef.deref(), opts))
+ })
+ }, opts.timeout)
+ return () => {
+ timers.clearFastTimeout(fastTimer)
+ clearImmediate(s1)
+ clearImmediate(s2)
+ }
+ }
+ : (socketWeakRef, opts) => {
+ if (!opts.timeout) {
+ return noop
}
- })
- }, timeout)
- return () => {
- clearTimeout(timeoutId)
- clearImmediate(s1)
- clearImmediate(s2)
+
+ let s1 = null
+ const fastTimer = timers.setFastTimeout(() => {
+ // setImmediate is added to make sure that we prioritize socket error events over timeouts
+ s1 = setImmediate(() => {
+ onConnectTimeout(socketWeakRef.deref(), opts)
+ })
+ }, opts.timeout)
+ return () => {
+ timers.clearFastTimeout(fastTimer)
+ clearImmediate(s1)
+ }
+ }
+
+/**
+ * @param {net.Socket} socket
+ * @param {object} opts
+ * @param {number} opts.timeout
+ * @param {string} opts.hostname
+ * @param {number} opts.port
+ */
+function onConnectTimeout (socket, opts) {
+ // The socket could be already garbage collected
+ if (socket == null) {
+ return
}
-}
-function onConnectTimeout (socket) {
- util.destroy(socket, new ConnectTimeoutError())
+ let message = 'Connect Timeout Error'
+ if (Array.isArray(socket.autoSelectFamilyAttemptedAddresses)) {
+ message += ` (attempted addresses: ${socket.autoSelectFamilyAttemptedAddresses.join(', ')},`
+ } else {
+ message += ` (attempted address: ${opts.hostname}:${opts.port},`
+ }
+
+ message += ` timeout: ${opts.timeout}ms)`
+
+ util.destroy(socket, new ConnectTimeoutError(message))
}
module.exports = buildConnector