Skip to content

Commit 2950c0d

Browse files
aduh95anonrig
authored andcommitted
url: allow extension of user provided URL objects
PR-URL: nodejs#46989 Fixes: nodejs#46981 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
1 parent 3897c5a commit 2950c0d

3 files changed

Lines changed: 51 additions & 13 deletions

File tree

doc/api/url.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1253,6 +1253,11 @@ pathToFileURL('/some/path%.c'); // Correct: file:///some/path%25.c (POSI
12531253
added:
12541254
- v15.7.0
12551255
- v14.18.0
1256+
changes:
1257+
- version: REPLACEME
1258+
pr-url: https://github.com/nodejs/node/pull/46989
1259+
description: The returned object will also contain all the own enumerable
1260+
properties of the `url` argument.
12561261
-->
12571262
12581263
* `url` {URL} The [WHATWG URL][] object to convert to an options object.

lib/internal/url.js

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1237,26 +1237,32 @@ function domainToUnicode(domain) {
12371237
return bindingUrl.domainToUnicode(`${domain}`);
12381238
}
12391239

1240-
// Utility function that converts a URL object into an ordinary
1241-
// options object as expected by the http.request and https.request
1242-
// APIs.
1240+
/**
1241+
* Utility function that converts a URL object into an ordinary options object
1242+
* as expected by the `http.request` and `https.request` APIs.
1243+
* @param {URL} url
1244+
* @returns {Record<string, unknown>}
1245+
*/
12431246
function urlToHttpOptions(url) {
1247+
const { hostname, pathname, port, username, password, search } = url;
12441248
const options = {
1249+
__proto__: null,
1250+
...url, // In case the url object was extended by the user.
12451251
protocol: url.protocol,
1246-
hostname: url.hostname && StringPrototypeStartsWith(url.hostname, '[') ?
1247-
StringPrototypeSlice(url.hostname, 1, -1) :
1248-
url.hostname,
1252+
hostname: hostname && StringPrototypeStartsWith(hostname, '[') ?
1253+
StringPrototypeSlice(hostname, 1, -1) :
1254+
hostname,
12491255
hash: url.hash,
1250-
search: url.search,
1251-
pathname: url.pathname,
1252-
path: `${url.pathname || ''}${url.search || ''}`,
1256+
search: search,
1257+
pathname: pathname,
1258+
path: `${pathname || ''}${search || ''}`,
12531259
href: url.href,
12541260
};
1255-
if (url.port !== '') {
1256-
options.port = Number(url.port);
1261+
if (port !== '') {
1262+
options.port = Number(port);
12571263
}
1258-
if (url.username || url.password) {
1259-
options.auth = `${decodeURIComponent(url.username)}:${decodeURIComponent(url.password)}`;
1264+
if (username || password) {
1265+
options.auth = `${decodeURIComponent(username)}:${decodeURIComponent(password)}`;
12601266
}
12611267
return options;
12621268
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const assert = require('node:assert');
5+
const http = require('node:http');
6+
7+
const headers = { foo: 'Bar' };
8+
const server = http.createServer(common.mustCall((req, res) => {
9+
assert.strictEqual(req.url, '/ping?q=term');
10+
assert.strictEqual(req.headers?.foo, headers.foo);
11+
req.resume();
12+
req.on('end', () => {
13+
res.writeHead(200);
14+
res.end('pong');
15+
});
16+
}));
17+
18+
server.listen(0, common.localhostIPv4, () => {
19+
const { address, port } = server.address();
20+
const url = new URL(`http://${address}:${port}/ping?q=term`);
21+
url.headers = headers;
22+
const clientReq = http.request(url);
23+
clientReq.on('close', common.mustCall(() => {
24+
server.close();
25+
}));
26+
clientReq.end();
27+
});

0 commit comments

Comments
 (0)