Skip to content

Bump express from 4.21.2 to 5.1.0 #9188

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

liranmauda
Copy link
Contributor

@liranmauda liranmauda commented Aug 10, 2025

Explain the Changes

  • Bump express from 4.21.2 to 5.1.0

Summary by CodeRabbit

  • New Features

    • No user-facing features added in this release.
  • Chores

    • Upgraded the web server framework to Express 5.1.0 for improved stability and modern middleware support.
  • Tests

    • Updated test server to use built-in request body parsing and explicit response termination.
    • Switched test responses to standardized JSON handling for consistency and correctness.
  • Documentation

    • No documentation changes.

Copy link

coderabbitai bot commented Aug 10, 2025

Walkthrough

Updated Express from 4.21.2 to 5.1.0 in package.json. Test server switched from body-parser to Express built-in parsers and ends POST responses explicitly. An integration test mock switches from res.send(JSON.stringify(...)) to res.json(...). No public API or export declarations were changed.

Changes

Cohort / File(s) Summary
Dependency upgrade
package.json
Bump express dependency from 4.21.2 to 5.1.0; no other dependency/script changes.
Test server middleware update
src/test/framework/server.js
Remove body-parser usage; use express.urlencoded and express.json; add explicit res.end() in POST handler; server port unchanged.
Integration test response method
src/test/integration_tests/nc/cli/test_cli_diagnose.test.js
Replace res.send(JSON.stringify(obj)) with res.json(obj) in metrics mock handler.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~15 minutes

Suggested labels

size/M

Suggested reviewers

  • jackyalbo
  • nimrod-becker
  • naveenpaul1

📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 50a7474 and f7d06d4.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (3)
  • package.json (1 hunks)
  • src/test/framework/server.js (1 hunks)
  • src/test/integration_tests/nc/cli/test_cli_diagnose.test.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/test/integration_tests/nc/cli/test_cli_diagnose.test.js
  • package.json
  • src/test/framework/server.js
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Build Noobaa Image
  • GitHub Check: run-package-lock-validation
  • GitHub Check: run-jest-unit-tests
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
src/server/web_server.js (2)

164-164: Minor nit: prefer redirect(status, url) or set trust proxy

Current usage is fine, but consider one of:

  • Use res.redirect(302, url) directly for clarity.
  • If behind proxies, app.set('trust proxy', true) and rely on req.secure or req.protocol rather than inspecting X-Forwarded-Proto manually.
- return res.status(302).redirect('https://' + host + req.originalUrl);
+ return res.redirect(302, 'https://' + host + req.originalUrl);

328-336: Error handler tidy-up looks good; minor hardening suggestion

Refactor is solid. Consider ensuring e.message is a string (avoid non-string payloads leaking) and avoid echoing raw messages in HTML in prod if they can be influenced by user input.

-    <h2>${e.message}</h2>
+    <h2>${String(e.message || 'Unexpected Error')}</h2>

Also applies to: 340-340

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 828d450 and f1f9c5d.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (4)
  • package.json (1 hunks)
  • src/server/web_server.js (8 hunks)
  • src/test/framework/server.js (0 hunks)
  • src/test/integration_tests/nc/cli/test_cli_diagnose.test.js (1 hunks)
💤 Files with no reviewable changes (1)
  • src/test/framework/server.js
🧰 Additional context used
📓 Path-based instructions (1)
src/test/**/*.*

⚙️ CodeRabbit Configuration File

src/test/**/*.*: Ensure that the PR includes tests for the changes.

Files:

  • src/test/integration_tests/nc/cli/test_cli_diagnose.test.js
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Build Noobaa Image
  • GitHub Check: run-jest-unit-tests
🔇 Additional comments (7)
src/test/integration_tests/nc/cli/test_cli_diagnose.test.js (1)

93-93: Good switch to res.json()

Using res.json(metrics_obj_mock) is the idiomatic and safer choice (sets headers, handles serialization). LGTM.

src/server/web_server.js (6)

95-96: LGTM: secure context update formatting

Minor cleanup looks good; no behavior change.


208-209: LGTM: explicit 200 and payload

Clearer than implicit defaults.


223-224: LGTM: simplified return shape

Concise and readable.


242-252: LGTM: early returns with sendStatus(500)

Consistent and prevents fallthrough.


311-311: LGTM: single send with explicit status

Straightforward and correct.


376-376: LGTM: concise early returns in version comparator

Clearer logic; no behavior change.

Also applies to: 386-386, 395-395

@@ -89,7 +89,7 @@
"chance": "1.1.13",
"compression": "1.8.1",
"crc-32": "1.2.2",
"express": "4.21.2",
"express": "5.1.0",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Express 5 upgrade: verify runtime compatibility and sweep for removed APIs

Express 5 requires modern Node versions and removes some legacy APIs. Please verify:

  • The production Node.js runtime satisfies Express 5’s minimum (recommend >= 18.18).
  • No remaining usages of removed/changed APIs (e.g., req.param(), res.sendfile(), res.json(status, body)).

Run this script to scan for incompatible patterns:

Optional: add an engines field to communicate the minimum Node version:

   "name": "noobaa-core",
   "version": "5.20.0",
+  "engines": {
+    "node": ">=18.18.0"
+  },

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Node engines field (if any):"
jq -r '.engines // {}' package.json || true

echo
echo "Scanning for removed/changed Express 5 APIs..."
# req.param(name) removed
rg -n -S 'req\.param\s*\(' || true
# res.sendfile (old) deprecated/removed
rg -n -S 'res\.sendfile\s*\(' || true
# Deprecated res.json(status, body) signature
rg -n -S 'res\.json\s*\(\s*\d+\s*,\s*' || true
# Deprecated res.send(status, body) signature
rg -n -S 'res\.send\s*\(\s*\d+\s*,\s*' || true
# Deprecated res.redirect(url, status) order (should be redirect(status, url))
rg -n -S 'res\.redirect\s*\(\s*[^,]+,\s*\d+\s*\)' || true

echo
echo "If running behind proxies, consider setting trust proxy explicitly."

Length of output: 694


Ensure Node.js ≥18.18.0 and validate Express 5 API usage

  • package.json currently lacks an engines field to enforce the minimum Node.js version.
  • Ripgrep scan confirms no legacy Express 5–removed APIs (req.param(), old res.json(status, body), res.send(status, body), or res.redirect(url, status)) remain.
    • The only hit was in src/server/license_info.js:46:
      res.sendFile(LICENSE_INFO_JSON_PATH);
      which is the correct modern API.
  • If your app runs behind proxies, explicitly configure trust proxy (e.g., app.set('trust proxy', true)).

Add this to package.json near the top level:

   "name": "noobaa-core",
   "version": "5.20.0",
+  "engines": {
+    "node": ">=18.18.0"
+  },
   "dependencies": {
     "express": "5.1.0",
     … 
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"express": "5.1.0",
"name": "noobaa-core",
"version": "5.20.0",
"engines": {
"node": ">=18.18.0"
},
"dependencies": {
"express": "5.1.0",
🤖 Prompt for AI Agents
In package.json at line 92, add an "engines" field at the top level specifying
"node" with a minimum version of "18.18.0" to enforce the required Node.js
version. Additionally, ensure that in your Express app initialization code you
configure trust proxy explicitly by adding app.set('trust proxy', true) if your
app runs behind proxies. This will enforce environment compatibility and proper
Express 5 usage.

Comment on lines 169 to 187
if (req.params[0] && req.params[0].includes('&curr=')) {
try {
const query_version = req.params[0].substr(req.params[0].indexOf('&curr=') + 6);
const query_version = req.params[0].substring(req.params[0].indexOf('&curr=') + 6);
let ret_version = '';

if (!is_latest_version(query_version)) {
ret_version = config.on_premise.base_url + process.env.CURRENT_VERSION + '/' + config.on_premise.nva_part;
}

res.status(200).send({
version: ret_version,
});
return res.status(200).send({ version: ret_version });
} catch (err) {
// nop
// noop
}
}
res.status(400).send({});
return res.status(400).send({});
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Bug: reading query string from req.params[0] breaks on Express 5; use req.query.curr

req.params[0] matches path wildcards, not the query string. As written, /get_latest_version?curr=1.2.3 will almost always return 400. Use req.query.curr instead, and fail fast when missing.

-function get_latest_version_handler(req, res) {
-    if (req.params[0] && req.params[0].includes('&curr=')) {
-        try {
-            const query_version = req.params[0].substring(req.params[0].indexOf('&curr=') + 6);
-            let ret_version = '';
-            if (!is_latest_version(query_version)) {
-                ret_version = config.on_premise.base_url + process.env.CURRENT_VERSION + '/' + config.on_premise.nva_part;
-            }
-            return res.status(200).send({ version: ret_version });
-        } catch (err) {
-            // noop
-        }
-    }
-    return res.status(400).send({});
-}
+function get_latest_version_handler(req, res) {
+    const query_version = req.query?.curr;
+    if (!query_version) return res.status(400).send({});
+    try {
+        let ret_version = '';
+        if (!is_latest_version(String(query_version))) {
+            ret_version = `${config.on_premise.base_url}${process.env.CURRENT_VERSION}/${config.on_premise.nva_part}`;
+        }
+        return res.status(200).send({ version: ret_version });
+    } catch (err) {
+        return res.sendStatus(500);
+    }
+}

I can add/update an integration test that asserts 200/400 behavior for /get_latest_version?curr=... after this fix. Want me to open a follow-up PR?

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (req.params[0] && req.params[0].includes('&curr=')) {
try {
const query_version = req.params[0].substr(req.params[0].indexOf('&curr=') + 6);
const query_version = req.params[0].substring(req.params[0].indexOf('&curr=') + 6);
let ret_version = '';
if (!is_latest_version(query_version)) {
ret_version = config.on_premise.base_url + process.env.CURRENT_VERSION + '/' + config.on_premise.nva_part;
}
res.status(200).send({
version: ret_version,
});
return res.status(200).send({ version: ret_version });
} catch (err) {
// nop
// noop
}
}
res.status(400).send({});
return res.status(400).send({});
}
function get_latest_version_handler(req, res) {
const query_version = req.query?.curr;
if (!query_version) return res.status(400).send({});
try {
let ret_version = '';
if (!is_latest_version(String(query_version))) {
ret_version = `${config.on_premise.base_url}${process.env.CURRENT_VERSION}/${config.on_premise.nva_part}`;
}
return res.status(200).send({ version: ret_version });
} catch (err) {
return res.sendStatus(500);
}
}
🤖 Prompt for AI Agents
In src/server/web_server.js around lines 169 to 182, the code incorrectly reads
the query string from req.params[0], which breaks in Express 5 because
req.params[0] captures path wildcards, not query parameters. To fix this,
replace all uses of req.params[0] and the substring extraction with direct
access to req.query.curr. Also, add a check to fail fast and return a 400 status
if req.query.curr is missing or empty.

Comment on lines 185 to 209
const module_name = req.params.module || req.query.module || req.body.module;
const level = req.params.level || req.query.level || req.body.level;

console.log('req.module', module_name, 'req.level', level);
if (!module_name || !level) {
return res.status(400).end();
}

dbg.log0('Change log level requested for', req.param('module'), 'to', req.param('level'));
dbg.set_module_level(req.param('level'), req.param('module'));
dbg.log0('Change log level requested for', module_name, 'to', level);
dbg.set_module_level(level, module_name);

await server_rpc.client.redirector.publish_to_cluster({
target: '', // required but irrelevant
target: '',
method_api: 'debug_api',
method_name: 'set_debug_level',
request_params: {
level: req.param('level'),
module: req.param('module')
}
request_params: { level, module: module_name }
});

res.status(200).end();
res.sendStatus(200);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Validate inputs and use dbg logger instead of console.log

  • console.log is inconsistent with the rest of the codebase logging; use dbg instead.
  • Validate module_name and level to avoid unexpected changes cluster-wide. At minimum, ensure both are non-empty strings; ideally, enforce an allowed levels set.
 async function set_log_level_handler(req, res) {
-    const module_name = req.params.module || req.query.module || req.body.module;
-    const level = req.params.level || req.query.level || req.body.level;
-
-    console.log('req.module', module_name, 'req.level', level);
-    if (!module_name || !level) {
-        return res.status(400).end();
-    }
-
-    dbg.log0('Change log level requested for', module_name, 'to', level);
+    const module_name = req.params?.module || req.query?.module || req.body?.module;
+    const level = req.params?.level || req.query?.level || req.body?.level;
+
+    if (typeof module_name !== 'string' || typeof level !== 'string' || !module_name || !level) {
+        return res.sendStatus(400);
+    }
+
+    dbg.log0('Change log level requested for', module_name, 'to', level);
     dbg.set_module_level(level, module_name);
 
     await server_rpc.client.redirector.publish_to_cluster({
         target: '',
         method_api: 'debug_api',
         method_name: 'set_debug_level',
         request_params: { level, module: module_name }
     });
 
     res.sendStatus(200);
 }

If request bodies are expected here, ensure a JSON or urlencoded body parser is configured (Express 5 does not include body-parsing by default):

 function setup_web_server_app(app) {
+    app.use(express.json());
+    app.use(express.urlencoded({ extended: false }));

Would you like a PR to wire this end-to-end and add tests?


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the web server setup function
rg "function setup_web_server_app" -n .

# Check for body parsers (JSON or urlencoded)
rg "express\\.json" -n .
rg "express\\.urlencoded" -n .
rg "bodyParser" -n .

# Find any console.log usages
rg "console\\.log" -n .

# Find dbg logging usage
rg "dbg\\.log" -n .

Length of output: 155


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show the setup_web_server_app implementation and nearby lines
rg -n -B5 -A20 "function setup_web_server_app" src/server/web_server.js

# Check for any body-parser or express.json/urlencoded configuration
rg -n "app.use" src/server/web_server.js

# Confirm this handler’s console.log usage
rg -n "console\\.log" src/server/web_server.js

# Confirm dbg.log0 usage
rg -n "dbg\\.log0" src/server/web_server.js

Length of output: 3010


Enforce input validation, remove console.log, and enable body parsing

Please address the following in src/server/web_server.js:

  • Replace the stray console.log in set_log_level_handler with dbg.log0
  • Validate that both module_name and level are non‐empty strings; return res.sendStatus(400) on failure
  • Wire up Express’s JSON and URL‐encoded body parsers before any routes that read req.body
  • Add tests covering missing, empty, or non‐string values for module and level

Suggested diff:

diff --git a/src/server/web_server.js b/src/server/web_server.js
index abcdef1..1234567 100644
--- a/src/server/web_server.js
+++ b/src/server/web_server.js
@@ function setup_web_server_app(app) {
-    app.use(express_morgan_logger(dev_mode ? 'dev' : 'combined'));
+    // parse JSON and URL‐encoded bodies before routes that use req.body
+    app.use(express.json());
+    app.use(express.urlencoded({ extended: false }));
+    app.use(express_morgan_logger(dev_mode ? 'dev' : 'combined'));
@@ async function set_log_level_handler(req, res) {
-    const module_name = req.params.module || req.query.module || req.body.module;
-    const level       = req.params.level  || req.query.level  || req.body.level;
-
-    console.log('req.module', module_name, 'req.level', level);
-    if (!module_name || !level) {
-        return res.status(400).end();
-    }
-
-    dbg.log0('Change log level requested for', module_name, 'to', level);
+    const module_name = req.params?.module || req.query?.module || req.body?.module;
+    const level       = req.params?.level  || req.query?.level  || req.body?.level;
+
+    // enforce non‐empty string values
+    if (typeof module_name !== 'string' || !module_name
+     || typeof level       !== 'string' || !level) {
+        return res.sendStatus(400);
+    }
+    dbg.log0('Change log level requested for', module_name, 'to', level);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const module_name = req.params.module || req.query.module || req.body.module;
const level = req.params.level || req.query.level || req.body.level;
console.log('req.module', module_name, 'req.level', level);
if (!module_name || !level) {
return res.status(400).end();
}
dbg.log0('Change log level requested for', req.param('module'), 'to', req.param('level'));
dbg.set_module_level(req.param('level'), req.param('module'));
dbg.log0('Change log level requested for', module_name, 'to', level);
dbg.set_module_level(level, module_name);
await server_rpc.client.redirector.publish_to_cluster({
target: '', // required but irrelevant
target: '',
method_api: 'debug_api',
method_name: 'set_debug_level',
request_params: {
level: req.param('level'),
module: req.param('module')
}
request_params: { level, module: module_name }
});
res.status(200).end();
res.sendStatus(200);
}
const module_name = req.params?.module || req.query?.module || req.body?.module;
const level = req.params?.level || req.query?.level || req.body?.level;
// enforce non-empty string values
if (typeof module_name !== 'string' || !module_name
|| typeof level !== 'string' || !level) {
return res.sendStatus(400);
}
dbg.log0('Change log level requested for', module_name, 'to', level);
dbg.set_module_level(level, module_name);
await server_rpc.client.redirector.publish_to_cluster({
target: '',
method_api: 'debug_api',
method_name: 'set_debug_level',
request_params: { level, module: module_name }
});
res.sendStatus(200);
}
🤖 Prompt for AI Agents
In src/server/web_server.js around lines 185 to 204, replace the console.log
call with dbg.log0 for consistent logging, validate that module_name and level
are non-empty strings and return res.sendStatus(400) if validation fails, ensure
Express JSON and URL-encoded body parsers are configured before routes accessing
req.body, and add tests to cover cases where module or level are missing, empty,
or not strings.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🔭 Outside diff range comments (3)
src/server/web_server.js (3)

148-166: Avoid open-redirect and Host-header poisoning in HTTPS redirect

Using req.get('Host') directly enables host-header attacks and open redirects. Prefer req.secure (with app.set('trust proxy', true)) and req.hostname.

 function https_redirect_handler(req, res, next) {
-    const fwd_proto = req.get('X-Forwarded-Proto');
-    if (fwd_proto === 'http') {
-        const host = req.get('Host');
-        return res.status(302).redirect('https://' + host + req.originalUrl);
-    }
-    return next();
+    // With trust proxy enabled, req.secure reflects x-forwarded-proto
+    if (!req.secure) {
+        const url = `https://${req.hostname}${req.originalUrl}`;
+        return res.redirect(302, url);
+    }
+    next();
 }

Add before any middleware in setup:

app.set('trust proxy', true);

220-227: Avoid double-ending responses in get_version_handler

Current flow can call res.send() then res.end() again. Set status first and send once.

// Suggested replacement (outside changed hunk for clarity)
async function get_version_handler(req, res) {
    if (config.NOOBAA_VERSION_AUTH_ENABLED && !http_utils.authorize_bearer(req, res)) return;
    const { status, version } = await getVersion(req.path);
    return res.status(status).send(version || '');
}

370-401: Harden is_latest_version: normalize inputs and use dbg instead of console.log

Guard against missing env var, ensure string inputs, and use dbg logging.

 function is_latest_version(query_version) {
-    const srv_version = process.env.CURRENT_VERSION;
-    console.log('Checking version', query_version, 'against', srv_version);
-
-    if (query_version === srv_version) return true;
+    const srv_version = process.env.CURRENT_VERSION;
+    dbg.log1('Checking version', query_version, 'against', srv_version);
+    if (!srv_version || !query_version) return true;
+    if (String(query_version) === String(srv_version)) return true;
@@
-        if (parseInt(srv_version_parts[i], 10) > parseInt(query_version_parts[i], 10)) return false;
+        if (parseInt(srv_version_parts[i], 10) > parseInt(query_version_parts[i], 10)) return false;
@@
-    if (srv_version_parts.length > query_version_parts.length) return false;
+    if (srv_version_parts.length > query_version_parts.length) return false;
♻️ Duplicate comments (2)
src/server/web_server.js (2)

168-182: Bug: reading query string from req.params[0] breaks on Express 5; use req.query.curr

req.params[0] matches a path wildcard, not the query string. This will cause /get_latest_version?curr=1.2.3 to return 400 most of the time.

 function get_latest_version_handler(req, res) {
-    if (req.params[0] && req.params[0].includes('&curr=')) {
-        try {
-            const query_version = req.params[0].substring(req.params[0].indexOf('&curr=') + 6);
-            let ret_version = '';
-            if (!is_latest_version(query_version)) {
-                ret_version = config.on_premise.base_url + process.env.CURRENT_VERSION + '/' + config.on_premise.nva_part;
-            }
-            return res.status(200).send({ version: ret_version });
-        } catch (err) {
-            // noop
-        }
-    }
-    return res.status(400).send({});
+    const query_version = req.query?.curr;
+    if (!query_version || typeof query_version !== 'string') return res.sendStatus(400);
+    try {
+        let ret_version = '';
+        if (!is_latest_version(String(query_version))) {
+            ret_version = `${config.on_premise.base_url}${process.env.CURRENT_VERSION}/${config.on_premise.nva_part}`;
+        }
+        return res.status(200).send({ version: ret_version });
+    } catch (err) {
+        dbg.warn('get_latest_version_handler failed', err);
+        return res.sendStatus(500);
+    }
 }

Optional: remove the wildcard from the route to avoid confusion:

  • Current (Line 120): app.get('/get_latest_version*', get_latest_version_handler);
  • Suggested: app.get('/get_latest_version', get_latest_version_handler);

I can add/adjust integration tests to assert 200/400 behavior for /get_latest_version?curr=....


184-204: Validate inputs, remove console.log, and wire body parsers (Express 5)

  • console.log is inconsistent with dbg.*.
  • Validate module_name/level as non-empty strings.
  • Express 5 does not bundle body parsing; req.body will be undefined without parsers.
 async function set_log_level_handler(req, res) {
-    const module_name = req.params.module || req.query.module || req.body.module;
-    const level = req.params.level || req.query.level || req.body.level;
-
-    console.log('req.module', module_name, 'req.level', level);
-    if (!module_name || !level) {
-        return res.status(400).end();
-    }
-
-    dbg.log0('Change log level requested for', module_name, 'to', level);
+    const module_name = req.params?.module || req.query?.module || req.body?.module;
+    const level = req.params?.level || req.query?.level || req.body?.level;
+    if (typeof module_name !== 'string' || !module_name ||
+        typeof level !== 'string' || !level) {
+        return res.sendStatus(400);
+    }
+    dbg.log0('Change log level requested for', module_name, 'to', level);
     dbg.set_module_level(level, module_name);
@@
-    res.sendStatus(200);
+    return res.sendStatus(200);
 }

Add body parsers early in setup (before routes that read req.body):

app.use(express.json());
app.use(express.urlencoded({ extended: false }));
#!/bin/bash
# Verify body parsers are configured and find req.body usages
rg -n "express\\.json|express\\.urlencoded|bodyParser" src/server/web_server.js
rg -n "req\\.body" -n
🧹 Nitpick comments (3)
src/server/web_server.js (3)

91-97: Nit: honorCipherOrder is not used by setSecureContext()

honorCipherOrder is a server option; it has no effect when passed to https_server.setSecureContext(...). Safe to omit for clarity.

- https_server.setSecureContext({ ...updated_cert_info.cert, honorCipherOrder: true });
+ https_server.setSecureContext({ ...updated_cert_info.cert });

309-311: Nit: explicitly set content-type to HTML

Be explicit since the payload contains <br> tags.

-    res.status(200).send(nsfs_report);
+    res.status(200).type('html').send(nsfs_report);

324-340: Error handler: standardize logging and simplify status handling

  • Prefer dbg.error over console.error.
  • Status normalization looks good; consider setting before building the HTML.
// Outside changed lines, but recommended:
dbg.error('ERROR:', err);
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f1f9c5d and adb6978.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (4)
  • package.json (1 hunks)
  • src/server/web_server.js (8 hunks)
  • src/test/framework/server.js (0 hunks)
  • src/test/integration_tests/nc/cli/test_cli_diagnose.test.js (1 hunks)
💤 Files with no reviewable changes (1)
  • src/test/framework/server.js
🚧 Files skipped from review as they are similar to previous changes (2)
  • package.json
  • src/test/integration_tests/nc/cli/test_cli_diagnose.test.js
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Build Noobaa Image
  • GitHub Check: run-jest-unit-tests
  • GitHub Check: run-package-lock-validation
🔇 Additional comments (1)
src/server/web_server.js (1)

206-209: LGTM: get_log_level_handler response

200 + JSON object is fine.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🔭 Outside diff range comments (2)
src/server/web_server.js (2)

120-121: Simplify the route; use query parameters instead of a wildcard

The handler should read the query (req.query.curr). The trailing * is unnecessary and misleading.

-    app.get('/get_latest_version*', get_latest_version_handler);
+    app.get('/get_latest_version', get_latest_version_handler);

111-116: Enable body parsers before routes that read req.body

Express 5 doesn’t include body parsing by default. Since set_log_level_handler reads req.body, parse bodies early.

     app.use(express_morgan_logger(dev_mode ? 'dev' : 'combined'));
+    // Parse request bodies before any route that accesses req.body
+    app.use(express.json());
+    app.use(express.urlencoded({ extended: false }));
     app.use(https_redirect_handler);
♻️ Duplicate comments (2)
src/server/web_server.js (2)

169-182: Bug: reading query from req.params[0] breaks on Express 5; use req.query.curr and proper error codes

req.params[0] captures wildcard path, not the query string. This will sporadically 400 even for valid requests. Also, swallowing errors with a noop hides server problems.

Apply:

-function get_latest_version_handler(req, res) {
-    if (req.params[0] && req.params[0].includes('&curr=')) {
-        try {
-            const query_version = req.params[0].substring(req.params[0].indexOf('&curr=') + 6);
-            let ret_version = '';
-            if (!is_latest_version(query_version)) {
-                ret_version = config.on_premise.base_url + process.env.CURRENT_VERSION + '/' + config.on_premise.nva_part;
-            }
-            return res.status(200).send({ version: ret_version });
-        } catch (err) {
-            // noop
-        }
-    }
-    return res.status(400).send({});
-}
+function get_latest_version_handler(req, res) {
+    const query_version = req.query?.curr;
+    if (typeof query_version !== 'string' || !query_version) {
+        return res.sendStatus(400);
+    }
+    try {
+        let ret_version = '';
+        if (!is_latest_version(String(query_version))) {
+            ret_version = `${config.on_premise.base_url}${process.env.CURRENT_VERSION}/${config.on_premise.nva_part}`;
+        }
+        return res.status(200).send({ version: ret_version });
+    } catch (err) {
+        dbg.warn('get_latest_version_handler failed', err);
+        return res.sendStatus(500);
+    }
+}

To verify tests cover this endpoint and its 200/400 behavior after the change, run:

#!/bin/bash
set -euo pipefail

# Find existing tests or callers of the endpoint
rg -n "get_latest_version" src/test || true
rg -n "/get_latest_version" || true

# Check for any lingering uses of req.params\\[0\\] patterns
rg -n "req\\.params\\s*\\[\\s*0\\s*\\]" src || true

184-204: set_log_level_handler: avoid crash on req.body access, validate inputs, and remove console.log

Accessing req.body.module when no body parser is configured throws. Also, prefer dbg logging and stronger validation.

 async function set_log_level_handler(req, res) {
-    const module_name = req.params.module || req.query.module || req.body.module;
-    const level = req.params.level || req.query.level || req.body.level;
-
-    console.log('req.module', module_name, 'req.level', level);
-    if (!module_name || !level) {
-        return res.status(400).end();
-    }
-
-    dbg.log0('Change log level requested for', module_name, 'to', level);
-    dbg.set_module_level(level, module_name);
+    const module_name = req.params?.module || req.query?.module || req.body?.module;
+    const level = req.params?.level || req.query?.level || req.body?.level;
+
+    if (typeof module_name !== 'string' || !module_name ||
+        typeof level !== 'string' || !level) {
+        return res.sendStatus(400);
+    }
+
+    dbg.log0('Change log level requested for', module_name, 'to', level);
+    dbg.set_module_level(level, module_name);
@@
-    res.sendStatus(200);
+    return res.sendStatus(200);
 }

Also ensure body parsers are configured before routes using req.body (see next comment).

🧹 Nitpick comments (3)
src/test/framework/server.js (1)

26-29: Return an explicit status in the POST handler for test stability

res.end() works, but tests are more robust with an explicit 2xx status. Consider 204 or echoing the body.

 app.post("*", function(req, res) {
   console.log(req.body);
-  res.end();
+  res.sendStatus(204);
 });
src/server/web_server.js (2)

95-96: Nit: honorCipherOrder is not used by setSecureContext

honorCipherOrder is a tls server option, not part of the secure context. Keep it on server creation; drop it here to avoid confusion.

-            https_server.setSecureContext({ ...updated_cert_info.cert, honorCipherOrder: true });
+            https_server.setSecureContext(updated_cert_info.cert);

370-401: Prefer dbg logging over console and harden version parsing

Optional cleanup:

  • Replace console.log/error with dbg logging for consistency.
  • Guard parseInt/Number conversions to avoid NaN pitfalls on non-numeric parts (e.g., prerelease tags).
-    console.log('Checking version', query_version, 'against', srv_version);
+    dbg.log1('Checking version', query_version, 'against', srv_version);
@@
-        if (parseInt(srv_version_parts[i], 10) > parseInt(query_version_parts[i], 10)) return false;
-        if (parseInt(srv_version_parts[i], 10) < parseInt(query_version_parts[i], 10)) {
-            console.error('BUG?! Queried version (', query_version, ') is higher than server version(',
-                srv_version, ') ! How can this happen?');
+        const a = Number(srv_version_parts[i]);
+        const b = Number(query_version_parts[i]);
+        if (!Number.isFinite(a) || !Number.isFinite(b)) break; // bail on non-numeric segment
+        if (a > b) return false;
+        if (a < b) {
+            dbg.warn('Queried version higher than server version', { query_version, srv_version });
             return true;
         }
@@
-    if (srv_version_parts.length > query_version_parts.length) return false;
+    if (srv_version_parts.length > query_version_parts.length) return false;
     if (srv_version_parts.length < query_version_parts.length) {
-        console.error('BUG?! Queried version (', query_version, ') is higher than server version(',
-            srv_version, '), has more tailing parts! How can this happen?');
+        dbg.warn('Queried version has more tailing parts than server version', { query_version, srv_version });
         return true;
     }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between adb6978 and 50a7474.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (4)
  • package.json (1 hunks)
  • src/server/web_server.js (8 hunks)
  • src/test/framework/server.js (1 hunks)
  • src/test/integration_tests/nc/cli/test_cli_diagnose.test.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/test/integration_tests/nc/cli/test_cli_diagnose.test.js
  • package.json
🧰 Additional context used
📓 Path-based instructions (1)
src/test/**/*.*

⚙️ CodeRabbit Configuration File

src/test/**/*.*: Ensure that the PR includes tests for the changes.

Files:

  • src/test/framework/server.js
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: run-jest-unit-tests
  • GitHub Check: Build Noobaa Image
🔇 Additional comments (6)
src/test/framework/server.js (1)

23-24: Express 5 built-in body parsing — LGTM

Good swap from body-parser to app.use(express.urlencoded(...)) and app.use(express.json()).

src/server/web_server.js (5)

163-164: Explicit 302 redirect — LGTM

Making the 302 explicit is fine and keeps intent clear.


208-209: get_log_level_handler response consolidation — LGTM


223-228: getVersion: concise return — LGTM


239-252: oauth_authorise_handler: concise error paths — LGTM

Using res.sendStatus(500) clarifies control-flow and avoids double-ends.


309-311: metrics_nsfs_stats_handler: single 200 send — LGTM

- Bump express from 4.21.2 to 5.1.0

Signed-off-by: liranmauda <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant