diff --git a/lib/agent.js b/lib/agent.js index d5163507526..320d7c473d8 100644 --- a/lib/agent.js +++ b/lib/agent.js @@ -1,7 +1,7 @@ 'use strict' const { InvalidArgumentError } = require('./core/errors') -const { kClients, kRunning, kClose, kDestroy, kDispatch, kInterceptors, kBusy } = require('./core/symbols') +const { kClients, kRunning, kClose, kDestroy, kDispatch, kInterceptors } = require('./core/symbols') const DispatcherBase = require('./dispatcher-base') const Pool = require('./pool') const Client = require('./client') @@ -15,7 +15,6 @@ const kMaxRedirections = Symbol('maxRedirections') const kOnDrain = Symbol('onDrain') const kFactory = Symbol('factory') const kOptions = Symbol('options') -const kDeleteScheduled = Symbol('deleteScheduled') function defaultFactory (origin, opts) { return opts && opts.connections === 1 @@ -94,34 +93,15 @@ class Agent extends DispatcherBase { if (!dispatcher) { dispatcher = this[kFactory](opts.origin, this[kOptions]) - .on('drain', (...args) => { - this[kOnDrain](...args) - - // We remove the client if it is not busy for 5 minutes - // to avoid a long list of clients to saturate memory. - // Ideally, we could use a FinalizationRegistry here, but - // it is currently very buggy in Node.js. - // See - // * https://github.com/nodejs/node/issues/49344 - // * https://github.com/nodejs/node/issues/47748 - // TODO(mcollina): make the timeout configurable or - // use an event to remove disconnected clients. - this[kDeleteScheduled] = setTimeout(() => { - if (dispatcher[kBusy] === 0) { - this[kClients].destroy().then(() => {}) - this[kClients].delete(key) - } - }, 300_000) - this[kDeleteScheduled].unref() - }) + .on('drain', this[kOnDrain]) .on('connect', this[kOnConnect]) .on('disconnect', this[kOnDisconnect]) .on('connectionError', this[kOnConnectionError]) + // This introduces a tiny memory leak, as dispatchers are never removed from the map. + // TODO(mcollina): remove te timer when the client/pool do not have any more + // active connections. this[kClients].set(key, dispatcher) - } else if (dispatcher[kDeleteScheduled]) { - clearTimeout(dispatcher[kDeleteScheduled]) - dispatcher[kDeleteScheduled] = null } return dispatcher.dispatch(opts, handler) diff --git a/lib/handler/RedirectHandler.js b/lib/handler/RedirectHandler.js index 34bba185d96..d8e96ddd844 100644 --- a/lib/handler/RedirectHandler.js +++ b/lib/handler/RedirectHandler.js @@ -176,7 +176,7 @@ function parseLocation (statusCode, headers) { } for (let i = 0; i < headers.length; i += 2) { - if (headers[i].toString().toLowerCase() === 'location') { + if (headers[i].length === 8 && util.headerNameToString(headers[i]) === 'location') { return headers[i + 1] } } @@ -184,12 +184,17 @@ function parseLocation (statusCode, headers) { // https://tools.ietf.org/html/rfc7231#section-6.4.4 function shouldRemoveHeader (header, removeContent, unknownOrigin) { - return ( - (header.length === 4 && header.toString().toLowerCase() === 'host') || - (removeContent && header.toString().toLowerCase().indexOf('content-') === 0) || - (unknownOrigin && header.length === 13 && header.toString().toLowerCase() === 'authorization') || - (unknownOrigin && header.length === 6 && header.toString().toLowerCase() === 'cookie') - ) + if (header.length === 4) { + return util.headerNameToString(header) === 'host' + } + if (removeContent && util.headerNameToString(header).startsWith('content-')) { + return true + } + if (unknownOrigin && (header.length === 13 || header.length === 6)) { + const name = util.headerNameToString(header) + return name === 'authorization' || name === 'cookie' + } + return false } // https://tools.ietf.org/html/rfc7231#section-6.4 diff --git a/package.json b/package.json index 9de9e1c29e4..197a968b392 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "undici", - "version": "6.2.0", + "version": "6.2.1", "description": "An HTTP/1.1 client, written from scratch for Node.js", "homepage": "https://undici.nodejs.org", "bugs": { @@ -119,7 +119,6 @@ "jsfuzz": "^1.0.15", "mitata": "^0.1.6", "mocha": "^10.0.0", - "mockttp": "^3.9.2", "p-timeout": "^3.2.0", "pre-commit": "^1.2.2", "proxy": "^1.0.2",