refactor: get rid of url.parse in core

This commit is contained in:
Barış Soner Uşaklı
2026-02-08 18:52:55 -05:00
parent fb460725ad
commit 157959df60
10 changed files with 37 additions and 33 deletions

View File

@@ -97,7 +97,7 @@
"multer": "2.0.2",
"nconf": "0.13.0",
"nodebb-plugin-2factor": "7.6.1",
"nodebb-plugin-composer-default": "10.3.10",
"nodebb-plugin-composer-default": "10.3.11",
"nodebb-plugin-dbsearch": "6.3.5",
"nodebb-plugin-emoji": "6.0.5",
"nodebb-plugin-emoji-android": "4.1.1",

View File

@@ -2,7 +2,6 @@
const nconf = require('nconf');
const fs = require('fs');
const url = require('url');
const path = require('path');
const { fork } = require('child_process');
const logrotate = require('logrotate-stream');
@@ -140,7 +139,7 @@ function getPorts() {
console.log('[cluster] url is undefined, please check your config.json');
process.exit();
}
const urlObject = url.parse(_url);
const urlObject = new URL(_url);
let port = nconf.get('PORT') || nconf.get('port') || urlObject.port || 4567;
if (!Array.isArray(port)) {
port = [port];

View File

@@ -198,10 +198,15 @@ ajaxify.widgets = { render: render };
ajaxify.currentPage = url.split(/[?#]/)[0];
ajaxify.requestedPage = null;
if (window.history && window.history.pushState) {
const prependSlash = url && !url.startsWith('?') && !url.startsWith('#');
const { relative_path } = config;
const historyUrl = prependSlash ?
(relative_path + '/' + url) :
relative_path + (url || (relative_path ? '' : '/'));
window.history[!quiet ? 'pushState' : 'replaceState']({
url: url,
}, '', relative_path + (url ? '/' + url : (relative_path ? '' : '/')));
}, '', historyUrl);
}
};
@@ -402,8 +407,11 @@ ajaxify.widgets = { render: render };
};
ajaxify.removeRelativePath = function (url) {
if (url.startsWith(config.relative_path.slice(1))) {
url = url.slice(config.relative_path.length);
if (config.relative_path && url.startsWith(config.relative_path.slice(1))) {
url = url.slice(config.relative_path.length - 1);
if (url.startsWith('/')) {
url = url.slice(1);
}
}
return url;
};
@@ -565,10 +573,16 @@ $(document).ready(function () {
if (ev !== null && ev.state) {
const { returnPath } = ev.state;
if (ev.state.url === null && returnPath !== undefined) {
const url = returnPath;
const prependSlash = url && !url.startsWith('?') && !url.startsWith('#');
const { relative_path } = config;
const historyUrl = prependSlash ?
(relative_path + '/' + url) :
relative_path + (url || (relative_path ? '' : '/'));
window.history.replaceState({
url: returnPath,
}, '', relative_path + (returnPath ? '/' + returnPath : (relative_path ? '' : '/')));
}, '', historyUrl);
} else if (ev.state.url !== undefined) {
ajaxify.handleTransientElements();
ajaxify.go(ev.state.url, function () {

View File

@@ -1,6 +1,5 @@
'use strict';
const url = require('url');
const user = require('../user');
const topics = require('../topics');
const posts = require('../posts');
@@ -29,7 +28,7 @@ exports.buildReqObject = (req, payload) => {
const referer = headers.referer || '';
if (!host) {
host = url.parse(referer).host || '';
host = new URL(referer).host || '';
}
return {

View File

@@ -1,7 +1,5 @@
'use strict';
const url = require('url');
const plugins = require('../plugins');
const meta = require('../meta');
const user = require('../user');
@@ -32,19 +30,19 @@ async function rewrite(req, res, next) {
let parsedUrl;
try {
parsedUrl = url.parse(route, true);
parsedUrl = new URL(route, 'http://localhost.com');
} catch (err) {
return next(err);
}
const { pathname } = parsedUrl;
const pathname = parsedUrl.pathname.replace(/^\/+/, '');
const hook = `action:homepage.get:${pathname}`;
if (!plugins.hooks.hasListeners(hook)) {
req.url = req.path + (!req.path.endsWith('/') ? '/' : '') + pathname;
} else {
res.locals.homePageRoute = pathname;
}
req.query = Object.assign(parsedUrl.query, req.query);
req.query = Object.assign(Object.fromEntries(parsedUrl.searchParams), req.query);
next();
}

View File

@@ -217,19 +217,17 @@ async function completeConfigSetup(config) {
}
// If port is explicitly passed via install vars, use it. Otherwise, glean from url if set.
const urlObj = url.parse(config.url);
const urlObj = new URL(config.url);
if (urlObj.port && (!install.values || !install.values.hasOwnProperty('port'))) {
config.port = urlObj.port;
}
// Remove trailing slash from non-subfolder installs
if (urlObj.path === '/') {
urlObj.path = '';
urlObj.pathname = '';
config.url = urlObj.toString();
// Remove trailing slash from URL
if (config.url.endsWith('/')) {
config.url = config.url.slice(0, -1);
}
config.url = url.format(urlObj);
// ref: https://github.com/indexzero/nconf/issues/300
delete config.type;

View File

@@ -1,7 +1,6 @@
'use strict';
const nconf = require('nconf');
const url = require('url');
const winston = require('winston');
const path = require('path');
const chalk = require('chalk');
@@ -89,12 +88,13 @@ function loadConfig(configFile) {
if (!nconf.get('sessionKey')) {
nconf.set('sessionKey', 'express.sid');
}
const url = nconf.get('url');
if (url) {
const urlObject = new URL(url);
if (nconf.get('url')) {
nconf.set('url', nconf.get('url').replace(/\/$/, ''));
nconf.set('url_parsed', url.parse(nconf.get('url')));
nconf.set('url', url.replace(/\/$/, ''));
nconf.set('url_parsed', urlObject);
// Parse out the relative_url and other goodies from the configured URL
const urlObject = url.parse(nconf.get('url'));
const relativePath = urlObject.pathname !== '/' ? urlObject.pathname.replace(/\/+$/, '') : '';
nconf.set('base_url', `${urlObject.protocol}//${urlObject.host}`);
nconf.set('secure', urlObject.protocol === 'https:');

View File

@@ -140,7 +140,7 @@ describe('authentication', () => {
it('should regenerate the session identifier on successful login', async () => {
const matchRegexp = /express\.sid=s%3A(.+?);/;
const { hostname, path } = url.parse(nconf.get('url'));
const { hostname, path } = new URL(nconf.get('url'));
const sid = String(jar.store.idx[hostname][path]['express.sid']).match(matchRegexp)[1];
await helpers.logoutUser(jar);
const newJar = (await helpers.loginUser('regular', 'regularpwd')).jar;

View File

@@ -46,7 +46,7 @@ nconf.defaults({
relative_path: '',
});
const urlObject = url.parse(nconf.get('url'));
const urlObject = new URL(nconf.get('url'));
const relativePath = urlObject.pathname !== '/' ? urlObject.pathname : '';
nconf.set('relative_path', relativePath);
nconf.set('asset_base_url', `${relativePath}/assets`);
@@ -134,9 +134,6 @@ module.exports = db;
before(async function () {
this.timeout(30000);
// Parse out the relative_url and other goodies from the configured URL
const urlObject = url.parse(nconf.get('url'));
nconf.set('core_templates_path', path.join(__dirname, '../../src/views'));
nconf.set('base_templates_path', path.join(nconf.get('themes_path'), 'nodebb-theme-persona/templates'));
nconf.set('theme_config', path.join(nconf.get('themes_path'), 'nodebb-theme-persona', 'theme.json'));

View File

@@ -1,7 +1,6 @@
'use strict';
const path = require('path');
const url = require('url');
const nconf = require('nconf');
const activePlugins = require('./build/active_plugins.json');
@@ -12,7 +11,7 @@ if (relativePath === undefined) {
file: path.resolve(__dirname, nconf.any(['config', 'CONFIG']) || 'config.json'),
});
const urlObject = url.parse(nconf.get('url'));
const urlObject = new URL(nconf.get('url'));
relativePath = urlObject.pathname !== '/' ? urlObject.pathname.replace(/\/+$/, '') : '';
}