From c1381e0454fb1fe8bb8d90c60807955b37c49907 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20K=C5=82ys?= Date: Mon, 17 Jul 2023 09:42:57 +0200 Subject: [PATCH] https: make https.globalAgent overridable also under ECMAScript Modules Under ECMAScript modules when you do "import * as https from 'https'" you get a new object with properties copied from https module exports. So if this is a regular data property, you will just override a copy, but if this would be a accessor property, we can still access the actual https.globalAgent. Refs: https://github.com/nodejs/node/pull/25170, https://github.com/nodejs/node/pull/9386 --- lib/https.js | 17 +++++++- ...est-https-client-override-global-agent.mjs | 43 +++++++++++++++++++ 2 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 test/parallel/test-https-client-override-global-agent.mjs diff --git a/lib/https.js b/lib/https.js index d8b42c85493f7e..801a5ee95063a3 100644 --- a/lib/https.js +++ b/lib/https.js @@ -30,6 +30,7 @@ const { FunctionPrototypeCall, JSONStringify, ObjectAssign, + ObjectDefineProperty, ObjectSetPrototypeOf, ReflectApply, ReflectConstruct, @@ -350,7 +351,7 @@ Agent.prototype._evictSession = function _evictSession(key) { delete this._sessionCache.map[key]; }; -const globalAgent = new Agent({ keepAlive: true, scheduling: 'lifo', timeout: 5000 }); +let globalAgent = new Agent({ keepAlive: true, scheduling: 'lifo', timeout: 5000 }); /** * Makes a request to a secure web server. @@ -415,9 +416,21 @@ function get(input, options, cb) { module.exports = { Agent, - globalAgent, Server, createServer, get, request, }; + +// Make https.globalAgent overridable also under ECMAScript Modules +ObjectDefineProperty(module.exports, 'globalAgent', { + __proto__: null, + configurable: true, + enumerable: true, + get() { + return globalAgent; + }, + set(value) { + globalAgent = value; + }, +}); diff --git a/test/parallel/test-https-client-override-global-agent.mjs b/test/parallel/test-https-client-override-global-agent.mjs new file mode 100644 index 00000000000000..3eb73175141c47 --- /dev/null +++ b/test/parallel/test-https-client-override-global-agent.mjs @@ -0,0 +1,43 @@ +import { hasCrypto, skip, mustCall } from '../common/index.mjs'; +if (!hasCrypto) skip('missing crypto'); +import { readKey } from '../common/fixtures.mjs'; +import assert from 'assert'; +// To override https.globalAgent we need to use namespace import +import * as https from 'https'; + +// Disable strict server certificate validation by the client +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; + +const options = { + key: readKey('agent1-key.pem'), + cert: readKey('agent1-cert.pem'), +}; + +const server = https.Server( + options, + mustCall((req, res) => { + res.writeHead(200); + res.end('Hello, World!'); + }) +); + +server.listen( + 0, + mustCall(() => { + const agent = new https.Agent(); + const name = agent.getName({ port: server.address().port }); + // That is exactly what we want here:) + /* eslint-disable no-import-assign */ + https.globalAgent = agent; + + makeRequest(); + assert(name in agent.sockets); // Agent has indeed been used + }) +); + +function makeRequest() { + const req = https.get({ + port: server.address().port, + }); + req.on('close', () => server.close()); +}