启用express-mongo-sanitize时报错:无法赋值只读属性'query'
问题:启用express-mongo-sanitize后出现只读属性赋值错误
这是基于MEAN栈构建的Web应用,运行环境为Node.js 20.18、Ubuntu 22.04、Angular 17.x(Angular的dist文件由Node项目托管)。访问应用URL时抛出错误,注释掉app.js中的app.use(mongoSanitize())后错误消失,但相同代码在另一台配置一致的VPS上运行正常,无法定位问题原因。
核心错误信息
TypeError: Cannot assign to read only property 'query' of object '#<IncomingMessage>' at /root/cops/node_modules/express-mongo-sanitize/index.js:113:18
app.js代码片段
const path = require("path") const mongoose = require('mongoose'); const express = require('express'); const bodyparser = require('body-parser'); const cookieParser = require('cookie-parser'); const crypto = require('crypto'); const { xss } = require('express-xss-sanitizer'); const helmet = require('helmet'); const mongoSanitize = require('express-mongo-sanitize'); const config = require('./config/config'); const morgan = require('./config/morgan'); const logger = require('./config/logger'); const ApiError = require('./helpers/ApiError'); const { errorHandlerNew, errorConvertor } = require('./middleware/errors'); const app = express(); app.use(morgan.successLogHandler); app.use(morgan.errorLogHandler); const connectStr = config.dbConnection + config.dbName; mongoose.connect(connectStr, mongooseOpts) .then(() => { logger.info('Connected to database'); }) .catch((err) => { logger.error('Database connection failed with error: ' + err); }); app.use(bodyparser.json()); app.use(bodyparser.urlencoded({extended: false})); app.use(cookieParser()); app.use(xss()); // app.use(mongoSanitize()); /// WHEN ENABLED GIVES ERROR app.use("/", express.static(path.join(__dirname, "angular"))); const myCors = { origin: ["http://localhost:4200","http://localhost:5200", ...], default: "http://localhost:4200" } app.use((req, res, next) => { // logger.info('app.js req.headers.origin: ' + req.headers.origin); let reqHeadersOrigin = ''; if(req.headers.origin) reqHeadersOrigin = req.headers.origin.toLowerCase(); const origin = myCors.origin.includes(reqHeadersOrigin) ? req.headers.origin : myCors.default; res.setHeader('Access-Control-Allow-Origin', origin); res.setHeader("Access-Control-Allow-Credentials", true); res.setHeader( 'Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization, x-client-key, x-client-token, x-client-secret'); res.setHeader( 'Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, OPTIONS') if (req.method === 'OPTIONS') { return res.status(200).end(); } next(); }); app.use((req, res, next) => { res.sendFile(path.join(__dirname, "angular", "index.html")); });
加载门户时的完整错误日志
10 Jan 2025, 10:47:06 pm: error: TypeError: Cannot assign to read only property 'query' of object '#<IncomingMessage>' at /root/cops/node_modules/express-mongo-sanitize/index.js:113:18 at Array.forEach (<anonymous>) at /root/cops/node_modules/express-mongo-sanitize/index.js:110:44 at Layer.handle [as handle_request] (/root/cops/node_modules/express/lib/router/layer.js:95:5) at trim_prefix (/root/cops/node_modules/express/lib/router/index.js:328:13) at /root/cops/node_modules/express/lib/router/index.js:286:9 at Function.process_params (/root/cops/node_modules/express/lib/router/index.js:346:12) at next (/root/cops/node_modules/express/lib/router/index.js:280:10) at /root/cops/node_modules/express-xss-sanitizer/index.js:19:5 at Layer.handle [as handle_request] (/root/cops/node_modules/express/lib/router/layer.js:95:5) at trim_prefix (/root/cops/node_modules/express/lib/router/index.js:328:13) at /root/cops/node_modules/express/lib/router/index.js:286:9 at Function.process_params (/root/cops/node_modules/express/lib/router/index.js:346:12) at next (/root/cops/node_modules/express/lib/router/index.js:280:10) at cookieParser (/root/cops/node_modules/cookie-parser/index.js:57:14) at Layer.handle [as handle_request] (/root/cops/node_modules/express/lib/router/layer.js:95:5) at trim_prefix (/root/cops/node_modules/express/lib/router/index.js:328:13) at /root/cops/node_modules/express/lib/router/index.js:286:9 at Function.process_params (/root/cops/node_modules/express/lib/router/index.js:346:12) at next (/root/cops/node_modules/express/lib/router/index.js:280:10) at urlencodedParser (/root/cops/node_modules/body-parser/lib/types/urlencoded.js:94:7) at Layer.handle [as handle_request] (/root/cops/node_modules/express/lib/router/layer.js:95:5)
错误截图

可能的原因与解决办法
依赖版本不一致
两台VPS配置看似一致,但实际依赖包版本可能存在差异。express-mongo-sanitize旧版本在Node.js 20+环境下,会尝试修改Express请求对象的只读query属性,触发报错。- 执行
npm list express-mongo-sanitize对比两台机器的版本,将问题机器的包升级到最新稳定版:npm install express-mongo-sanitize@latest
- 执行
Express版本兼容性
Node.js 20对对象属性的只读限制更严格,旧版Express的请求对象query属性可能被设为只读,导致中间件无法修改。- 升级Express到兼容版本:
npm install express@latest
- 升级Express到兼容版本:
调整中间件顺序
当前代码中mongoSanitize放在xss之后,尝试将其移到bodyparser之后、xss之前,避免中间件修改请求对象的顺序冲突:app.use(bodyparser.json()); app.use(bodyparser.urlencoded({extended: false})); app.use(cookieParser()); app.use(mongoSanitize()); // 调整到xss之前 app.use(xss());使用配置选项避免修改原对象
启用express-mongo-sanitize的replaceWith选项,不直接修改原query对象,而是返回 sanitize 后的新对象:app.use(mongoSanitize({ replaceWith: '_' }));
内容的提问来源于stack exchange,提问作者hemant
相关产品推荐
相关产品推荐

