Skip to content

Commit

Permalink
Prefer native URL instead of deprecated url.parse.
Browse files Browse the repository at this point in the history
  • Loading branch information
RubenVerborgh committed Dec 30, 2023
1 parent 1cba8e8 commit 05629af
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 35 deletions.
82 changes: 48 additions & 34 deletions index.js
Expand Up @@ -9,6 +9,20 @@ var debug = require("./debug");
// Whether to use the native URL object or the legacy url module
var hasNativeURL = typeof URL !== "undefined";

// URL fields to preserve in copy operations
var preservedUrlFields = [
"auth",
"host",
"hostname",
"href",
"path",
"pathname",
"port",
"protocol",
"query",
"search",
];

// Create handlers that pass events from native requests
var events = ["abort", "aborted", "connect", "error", "socket", "timeout"];
var eventHandlers = Object.create(null);
Expand Down Expand Up @@ -423,26 +437,23 @@ RedirectableRequest.prototype._processResponse = function (response) {
var currentHostHeader = removeMatchingHeaders(/^host$/i, this._options.headers);

// If the redirect is relative, carry over the host of the last request
var currentUrlParts = url.parse(this._currentUrl);
var currentUrlParts = parseUrl(this._currentUrl);
var currentHost = currentHostHeader || currentUrlParts.host;
var currentUrl = /^\w+:/.test(location) ? this._currentUrl :
url.format(Object.assign(currentUrlParts, { host: currentHost }));

// Determine the URL of the redirection
var redirectUrl = resolveUrl(location, currentUrl);

// Create the redirected request
debug("redirecting to", redirectUrl);
var redirectUrl = resolveUrl(location, currentUrl);
debug("redirecting to", redirectUrl.href);
this._isRedirect = true;
var redirectUrlParts = url.parse(redirectUrl);
Object.assign(this._options, redirectUrlParts);
spreadUrlObject(redirectUrl, this._options);

// Drop confidential headers when redirecting to a less secure protocol
// or to a different domain that is not a superdomain
if (redirectUrlParts.protocol !== currentUrlParts.protocol &&
redirectUrlParts.protocol !== "https:" ||
redirectUrlParts.host !== currentHost &&
!isSubdomain(redirectUrlParts.host, currentHost)) {
if (redirectUrl.protocol !== currentUrlParts.protocol &&
redirectUrl.protocol !== "https:" ||
redirectUrl.host !== currentHost &&
!isSubdomain(redirectUrl.host, currentHost)) {
removeMatchingHeaders(/^(?:authorization|cookie)$/i, this._options.headers);
}

Expand Down Expand Up @@ -486,7 +497,7 @@ function wrap(protocols) {
if (isString(input)) {
var parsed;
try {
parsed = urlToOptions(new URL(input));
parsed = spreadUrlObject(new URL(input));
}
catch (err) {
/* istanbul ignore next */
Expand All @@ -498,7 +509,7 @@ function wrap(protocols) {
input = parsed;
}
else if (hasNativeURL && (input instanceof URL)) {
input = urlToOptions(input);
input = spreadUrlObject(input);
}
else {
callback = options;
Expand Down Expand Up @@ -543,31 +554,34 @@ function wrap(protocols) {

function noop() { /* empty */ }

This comment has been minimized.

Copy link
@Renanluizssx

Renanluizssx Jan 22, 2024

if you aren't using this function, you could delete


function parseUrl(string) {
/* istanbul ignore next */
return hasNativeURL ? new URL(string) : url.parse(string);
}

function resolveUrl(relative, base) {
return !hasNativeURL ?
/* istanbul ignore next */
url.resolve(base, relative) :
(new URL(relative, base)).href;
/* istanbul ignore next */
return hasNativeURL ? new URL(relative, base) : parseUrl(url.resolve(base, relative));
}

// from https://github.com/nodejs/node/blob/master/lib/internal/url.js
function urlToOptions(urlObject) {
var options = {
protocol: urlObject.protocol,
hostname: urlObject.hostname.startsWith("[") ?
/* istanbul ignore next */
urlObject.hostname.slice(1, -1) :
urlObject.hostname,
hash: urlObject.hash,
search: urlObject.search,
pathname: urlObject.pathname,
path: urlObject.pathname + urlObject.search,
href: urlObject.href,
};
if (urlObject.port !== "") {
options.port = Number(urlObject.port);
function spreadUrlObject(urlObject, target) {
var spread = target || {};
for (var key of preservedUrlFields) {
spread[key] = urlObject[key];
}

// Fix IPv6 hostname
if (spread.hostname.startsWith("[")) {
spread.hostname = spread.hostname.slice(1, -1);
}
return options;
// Ensure port is a number
if (spread.port !== "") {
spread.port = Number(spread.port);
}
// Concatenate path
spread.path = spread.search ? spread.pathname + spread.search : spread.pathname;

return spread;
}

function removeMatchingHeaders(regex, headers) {
Expand Down
2 changes: 1 addition & 1 deletion test/test.js
Expand Up @@ -364,7 +364,7 @@ describe("follow-redirects", function () {
switch (error.cause.code) {
// Node 17+
case "ERR_INVALID_URL":
assert.match(error.message, /^Redirected request failed: Invalid URL/);
assert(/^Redirected request failed: Invalid URL/.test(error.message));
break;
// Older Node versions
case "ERR_UNESCAPED_CHARACTERS":
Expand Down

0 comments on commit 05629af

Please sign in to comment.