From 8e50c9d9078859444c8d03ba253ed23465f42ad5 Mon Sep 17 00:00:00 2001 From: Arthur Fiorette Date: Wed, 11 Mar 2026 12:36:00 -0300 Subject: [PATCH 1/8] code --- lib/util/s3_setup.js | 5 ++--- lib/util/versioning.js | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/util/s3_setup.js b/lib/util/s3_setup.js index ccbfa74e..fc9e1bc3 100644 --- a/lib/util/s3_setup.js +++ b/lib/util/s3_setup.js @@ -2,13 +2,12 @@ module.exports = exports; -const url = require('url'); module.exports.detect = function(opts) { const config = {}; const to = opts.hosted_path; - const uri = url.parse(to); + const uri = new URL(to); if (opts.bucket && opts.region) { // use user defined settings for host, region, bucket @@ -29,7 +28,7 @@ module.exports.detect = function(opts) { // https://bucket-name.s3.Region.amazonaws.com/key-name (dash Region) // or in some legacy region of this format: // https://bucket-name.s3-Region.amazonaws.com/key-name (dot Region) - const parts = uri.hostname.split('.s3'); + const parts = uri.hostname.replace(/^\[|\]$/, '').split('.s3'); // there is nothing before the .s3 // not a valid s3 virtual host bucket url diff --git a/lib/util/versioning.js b/lib/util/versioning.js index b69b367e..2155f833 100644 --- a/lib/util/versioning.js +++ b/lib/util/versioning.js @@ -221,7 +221,7 @@ function validate_config(package_json, opts) { } if (o) { // enforce https over http - const protocol = url.parse(o.host).protocol; + const protocol = new URL(o.host).protocol; if (protocol === 'http:') { throw new Error("'host' protocol (" + protocol + ") is invalid - only 'https:' is accepted"); } From 8d1d2fbfa97b5ef145927b547093b6a29a01fa69 Mon Sep 17 00:00:00 2001 From: Arthur Fiorette Date: Wed, 11 Mar 2026 12:40:12 -0300 Subject: [PATCH 2/8] url_resolve --- lib/util/versioning.js | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/util/versioning.js b/lib/util/versioning.js index 2155f833..8b79af27 100644 --- a/lib/util/versioning.js +++ b/lib/util/versioning.js @@ -4,7 +4,6 @@ module.exports = exports; const path = require('path'); const semver = require('semver'); -const url = require('url'); const detect_libc = require('detect-libc'); const napi = require('./napi.js'); @@ -241,6 +240,18 @@ function eval_template(template, opts) { return template; } +// url.resolve is deprecated because it invokes the deprecated url.parse() internally +// https://nodejs.org/api/url.html#urlresolvefrom-to +function url_resolve(from, to) { + const resolvedUrl = new URL(to, new URL(from, 'resolve://')); + if (resolvedUrl.protocol === 'resolve:') { + // `from` is a relative URL. + const { pathname, search, hash } = resolvedUrl; + return pathname + search + hash; + } + return resolvedUrl.toString(); +} + // url.resolve needs single trailing slash // to behave correctly, otherwise a double slash // may end up in the url which breaks requests @@ -333,10 +344,10 @@ module.exports.evaluate = function(package_json, options, napi_build_version) { // when using s3ForcePathStyle the bucket is part of the http object path // add it if (opts.s3ForcePathStyle) { - opts.hosted_path = url.resolve(opts.host, drop_double_slashes(`${opts.bucket}/${opts.remote_path}`)); + opts.hosted_path = url_resolve(opts.host, drop_double_slashes(`${opts.bucket}/${opts.remote_path}`)); } else { - opts.hosted_path = url.resolve(opts.host, opts.remote_path); + opts.hosted_path = url_resolve(opts.host, opts.remote_path); } - opts.hosted_tarball = url.resolve(opts.hosted_path, opts.package_name); + opts.hosted_tarball = url_resolve(opts.hosted_path, opts.package_name); return opts; }; From 3216579484395e1ab96375fc44fcc63886ea7ea3 Mon Sep 17 00:00:00 2001 From: Arthur Fiorette Date: Wed, 11 Mar 2026 12:42:49 -0300 Subject: [PATCH 3/8] remaining url imports --- lib/install.js | 2 +- lib/publish.js | 2 +- lib/unpublish.js | 2 +- lib/util/url.js | 11 +++++++++++ lib/util/versioning.js | 18 ++++-------------- 5 files changed, 18 insertions(+), 17 deletions(-) create mode 100644 lib/util/url.js diff --git a/lib/install.js b/lib/install.js index 82705428..92c80d57 100644 --- a/lib/install.js +++ b/lib/install.js @@ -11,7 +11,7 @@ const existsAsync = fs.exists || path.exists; const versioning = require('./util/versioning.js'); const napi = require('./util/napi.js'); const s3_setup = require('./util/s3_setup.js'); -const url = require('url'); +const url = require('./util/url.js'); // for fetching binaries const fetch = require('node-fetch'); const tar = require('tar'); diff --git a/lib/publish.js b/lib/publish.js index 23ef53b8..3727f2b3 100644 --- a/lib/publish.js +++ b/lib/publish.js @@ -11,7 +11,7 @@ const versioning = require('./util/versioning.js'); const napi = require('./util/napi.js'); const s3_setup = require('./util/s3_setup.js'); const existsAsync = fs.exists || path.exists; -const url = require('url'); +const url = require('./util/url.js'); function publish(gyp, argv, callback) { const package_json = gyp.package_json; diff --git a/lib/unpublish.js b/lib/unpublish.js index cb198e39..99da3abb 100644 --- a/lib/unpublish.js +++ b/lib/unpublish.js @@ -8,7 +8,7 @@ const log = require('./util/log.js'); const versioning = require('./util/versioning.js'); const napi = require('./util/napi.js'); const s3_setup = require('./util/s3_setup.js'); -const url = require('url'); +const url = require('./util/url.js'); function unpublish(gyp, argv, callback) { const package_json = gyp.package_json; diff --git a/lib/util/url.js b/lib/util/url.js new file mode 100644 index 00000000..1f26db37 --- /dev/null +++ b/lib/util/url.js @@ -0,0 +1,11 @@ +// url.resolve is deprecated because it invokes the deprecated url.parse() internally +// https://nodejs.org/api/url.html#urlresolvefrom-to +module.exports.resolve = function (from, to) { + const resolvedUrl = new URL(to, new URL(from, 'resolve://')); + if (resolvedUrl.protocol === 'resolve:') { + // `from` is a relative URL. + const { pathname, search, hash } = resolvedUrl; + return pathname + search + hash; + } + return resolvedUrl.toString(); +}; diff --git a/lib/util/versioning.js b/lib/util/versioning.js index 8b79af27..f899c1c1 100644 --- a/lib/util/versioning.js +++ b/lib/util/versioning.js @@ -6,6 +6,7 @@ const path = require('path'); const semver = require('semver'); const detect_libc = require('detect-libc'); const napi = require('./napi.js'); +const url = require('./url.js'); let abi_crosswalk; @@ -240,17 +241,6 @@ function eval_template(template, opts) { return template; } -// url.resolve is deprecated because it invokes the deprecated url.parse() internally -// https://nodejs.org/api/url.html#urlresolvefrom-to -function url_resolve(from, to) { - const resolvedUrl = new URL(to, new URL(from, 'resolve://')); - if (resolvedUrl.protocol === 'resolve:') { - // `from` is a relative URL. - const { pathname, search, hash } = resolvedUrl; - return pathname + search + hash; - } - return resolvedUrl.toString(); -} // url.resolve needs single trailing slash // to behave correctly, otherwise a double slash @@ -344,10 +334,10 @@ module.exports.evaluate = function(package_json, options, napi_build_version) { // when using s3ForcePathStyle the bucket is part of the http object path // add it if (opts.s3ForcePathStyle) { - opts.hosted_path = url_resolve(opts.host, drop_double_slashes(`${opts.bucket}/${opts.remote_path}`)); + opts.hosted_path = url.resolve(opts.host, drop_double_slashes(`${opts.bucket}/${opts.remote_path}`)); } else { - opts.hosted_path = url_resolve(opts.host, opts.remote_path); + opts.hosted_path = url.resolve(opts.host, opts.remote_path); } - opts.hosted_tarball = url_resolve(opts.hosted_path, opts.package_name); + opts.hosted_tarball = url.resolve(opts.hosted_path, opts.package_name); return opts; }; From bfd01f51a689c6074ea3ea63497685e9e8c069ae Mon Sep 17 00:00:00 2001 From: Arthur Fiorette Date: Wed, 11 Mar 2026 12:49:08 -0300 Subject: [PATCH 4/8] fix --- lib/util/s3_setup.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/util/s3_setup.js b/lib/util/s3_setup.js index fc9e1bc3..872638de 100644 --- a/lib/util/s3_setup.js +++ b/lib/util/s3_setup.js @@ -28,7 +28,7 @@ module.exports.detect = function(opts) { // https://bucket-name.s3.Region.amazonaws.com/key-name (dash Region) // or in some legacy region of this format: // https://bucket-name.s3-Region.amazonaws.com/key-name (dot Region) - const parts = uri.hostname.replace(/^\[|\]$/, '').split('.s3'); + const parts = uri.hostname.split('.s3'); // there is nothing before the .s3 // not a valid s3 virtual host bucket url From 48871ecc3a55cdb50920bc8782272b64587593ef Mon Sep 17 00:00:00 2001 From: Arthur Fiorette Date: Wed, 11 Mar 2026 12:49:42 -0300 Subject: [PATCH 5/8] format --- lib/util/versioning.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/util/versioning.js b/lib/util/versioning.js index f899c1c1..8b0e80ab 100644 --- a/lib/util/versioning.js +++ b/lib/util/versioning.js @@ -241,7 +241,6 @@ function eval_template(template, opts) { return template; } - // url.resolve needs single trailing slash // to behave correctly, otherwise a double slash // may end up in the url which breaks requests From f9e75ffb3f198d72f95be5b6d051dbf17b910703 Mon Sep 17 00:00:00 2001 From: Arthur Fiorette Date: Wed, 11 Mar 2026 12:52:51 -0300 Subject: [PATCH 6/8] Fix linting issues --- lib/util/url.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/util/url.js b/lib/util/url.js index 1f26db37..e9e38130 100644 --- a/lib/util/url.js +++ b/lib/util/url.js @@ -1,6 +1,8 @@ +'use strict'; + // url.resolve is deprecated because it invokes the deprecated url.parse() internally // https://nodejs.org/api/url.html#urlresolvefrom-to -module.exports.resolve = function (from, to) { +module.exports.resolve = function(from, to) { const resolvedUrl = new URL(to, new URL(from, 'resolve://')); if (resolvedUrl.protocol === 'resolve:') { // `from` is a relative URL. From 74ebc16e1837fe1916758802b7d3bf94e9e6895f Mon Sep 17 00:00:00 2001 From: Arthur Fiorette Date: Wed, 11 Mar 2026 13:06:01 -0300 Subject: [PATCH 7/8] Fix tests --- lib/util/s3_setup.js | 2 +- lib/util/versioning.js | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/util/s3_setup.js b/lib/util/s3_setup.js index 872638de..fc9e1bc3 100644 --- a/lib/util/s3_setup.js +++ b/lib/util/s3_setup.js @@ -28,7 +28,7 @@ module.exports.detect = function(opts) { // https://bucket-name.s3.Region.amazonaws.com/key-name (dash Region) // or in some legacy region of this format: // https://bucket-name.s3-Region.amazonaws.com/key-name (dot Region) - const parts = uri.hostname.split('.s3'); + const parts = uri.hostname.replace(/^\[|\]$/, '').split('.s3'); // there is nothing before the .s3 // not a valid s3 virtual host bucket url diff --git a/lib/util/versioning.js b/lib/util/versioning.js index 8b0e80ab..7a5a52f2 100644 --- a/lib/util/versioning.js +++ b/lib/util/versioning.js @@ -221,9 +221,13 @@ function validate_config(package_json, opts) { } if (o) { // enforce https over http - const protocol = new URL(o.host).protocol; - if (protocol === 'http:') { - throw new Error("'host' protocol (" + protocol + ") is invalid - only 'https:' is accepted"); + try { + const protocol = new URL(o.host).protocol; + if (protocol === 'http:') { + throw new Error("'host' protocol (" + protocol + ") is invalid - only 'https:' is accepted"); + } + } catch (err) { + // do nothing } } napi.validate_package_json(package_json, opts); From 69fb6cc745c1c8508cb3b7f85a8af8c636b91a21 Mon Sep 17 00:00:00 2001 From: Arthur Fiorette Date: Wed, 11 Mar 2026 13:11:48 -0300 Subject: [PATCH 8/8] fix tests --- lib/util/url.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/util/url.js b/lib/util/url.js index e9e38130..d548a906 100644 --- a/lib/util/url.js +++ b/lib/util/url.js @@ -7,6 +7,12 @@ module.exports.resolve = function(from, to) { if (resolvedUrl.protocol === 'resolve:') { // `from` is a relative URL. const { pathname, search, hash } = resolvedUrl; + + // To keep consistency with deprecated url.resolve(), we need to remove the leading '/' from pathname + if (pathname[0] === '/') { + return pathname.slice(1) + search + hash; + } + return pathname + search + hash; } return resolvedUrl.toString();