Strapi全局自定义中间件报错:strapi解构未定义的解决方法
解决Strapi自定义全局中间件启动报错问题
问题场景
我正在为Strapi开发一个可将响应体转换为哈希值的自定义中间件,需要全局应用到所有路由。通过npx strapi generate生成中间件,用npx strapi middlewares:list确认名称后,在./config/middlewares.js中添加了'global::ctx-decrypt'配置,但启动Strapi时报错:Cannot destructure property 'strapi' of 'undefined' as it is undefined。
原中间件代码
'use strict'; /** * `ctx-decrypt` middleware. */ var crypto = require('crypto'); const algorithm = 'aes-256-cbc'; function decrypt(text,key) { let iv = Buffer.from(text.iv, 'hex'); let encryptedText = Buffer.from(text.encryptedData, 'hex'); let decipher = crypto.createDecipheriv('aes-256-cbc', Buffer.from(key), iv); let decrypted = decipher.update(encryptedText); decrypted = Buffer.concat([decrypted, decipher.final()]); return decrypted.toString(); } function hash(data) { var hash = crypto.createHash('sha256', data); return hash; } module.exports = (config,{env},{strapi}) => { return { initialize() { strapi.app.use(async (ctx, next) => { strapi.log.info('In ctx-decrypt middleware.'); var ENC_KEY = process.env.ENC_KEY; var requestBody = ctx.request.body; //var responseBody = ctx.body; var dc = decrypt(requestBody,ENC_KEY); if(!dc) { throw new Error('Invalid request body!'); ctx.response.set(hash("5u5234803riqifn")); console.log(ctx.body) await next(); } else { ctx.response.set(hash("5u5234803riqifn")); console.log(ctx.body) await next(); } }); } }; };
错误日志
0|super-fu | [2022-12-23 02:48:51.181] debug: ⛔️ Server wasn't able to start properly. 0|super-fu | [2022-12-23 02:48:51.183] error: Middleware "global::ctx-decrypt": Cannot destructure property 'strapi' of 'undefined' as it is undefined. 0|super-fu | Error: Middleware "global::ctx-decrypt": Cannot destructure property 'strapi' of 'undefined' as it is undefined. 0|super-fu | at instantiateMiddleware (/home/blackhole/nodejs/super-funnels/super-funnels-backend/node_modules/@strapi/strapi/lib/services/server/middleware.js:12:11) 0|super-fu | at resolveMiddlewares (/home/blackhole/nodejs/super-funnels/super-funnels-backend/node_modules/@strapi/strapi/lib/services/server/middleware.js:56:18) 0|super-fu | at registerApplicationMiddlewares (/home/blackhole/nodejs/super-funnels/super-funnels-backend/node_modules/@strapi/strapi/lib/services/server/register-middlewares.js:66:29) 0|super-fu | at process.processTicksAndRejections (node:internal/process/task_queues:95:5) 0|super-fu | at async Object.initMiddlewares (/home/blackhole/nodejs/super-funnels/super-funnels-backend/node_modules/@strapi/strapi/lib/services/server/index.js:99:7) 0|super-fu | at async Strapi.bootstrap (/home/blackhole/nodejs/super-funnels/super-funnels-backend/node_modules/@strapi/strapi/lib/Strapi.js:414:5) 0|super-fu | at async Strapi.load (/home/blackhole/nodejs/super-funnels/super-funnels-backend/node_modules/@strapi/strapi/lib/Strapi.js:426:5) 0|super-fu | at async Strapi.start (/home/blackhole/nodejs/super-funnels/super-funnels-backend/node_modules/@strapi/strapi/lib/Strapi.js:169:9) 0|super-fu | 0|super-fu | > super-funnels-backend@0.1.0 start 0|super-fu | > strapi start
错误原因分析
- 中间件导出参数结构错误:Strapi v4的全局中间件导出函数仅接受两个参数,第一个是配置对象,第二个是包含
strapi和env的上下文对象。你错误地拆分成三个参数,导致第三个参数{strapi}为undefined,解构时抛出错误。 - JavaScript自动分号插入(ASI)问题:
return语句后直接换行,JavaScript会自动在return后插入分号,导致实际返回undefined,而非你定义的包含initialize方法的对象。 - 其他逻辑问题:
hash函数未正确生成哈希值(需调用digest());throw new Error()之后的代码永远不会执行;设置响应头的逻辑顺序错误。
修复方案及修正后代码
核心修正点
- 调整导出函数参数为
(config, { strapi, env }),合并上下文对象 - 将
return与后续对象放在同一行,避免ASI问题 - 修复
hash函数,调用digest()生成实际哈希字符串 - 调整逻辑顺序,确保错误处理和中间件执行流程正确
修正后完整代码
'use strict'; /** * `ctx-decrypt` middleware. */ const crypto = require('crypto'); const algorithm = 'aes-256-cbc'; function decrypt(text, key) { let iv = Buffer.from(text.iv, 'hex'); let encryptedText = Buffer.from(text.encryptedData, 'hex'); let decipher = crypto.createDecipheriv('aes-256-cbc', Buffer.from(key), iv); let decrypted = decipher.update(encryptedText); decrypted = Buffer.concat([decrypted, decipher.final()]); return decrypted.toString(); } function hash(data) { const hash = crypto.createHash('sha256'); hash.update(data); return hash.digest('hex'); // 生成十六进制哈希字符串 } module.exports = (config, { strapi, env }) => { return { // return与对象在同一行,避免ASI问题 initialize() { strapi.app.use(async (ctx, next) => { strapi.log.info('In ctx-decrypt middleware.'); const ENC_KEY = process.env.ENC_KEY; const requestBody = ctx.request.body; try { // 解密请求体 const dc = decrypt(requestBody, ENC_KEY); // 替换请求体为解密后的数据,供后续路由使用 ctx.request.body = JSON.parse(dc); // 先执行后续中间件和路由处理 await next(); // 处理响应:生成哈希并设置响应头 const responseHash = hash("5u5234803riqifn"); ctx.response.set('X-Response-Hash', responseHash); strapi.log.info('Response hash set:', responseHash); } catch (err) { // 处理解密失败或其他错误 strapi.log.error('Middleware error:', err.message); const errorHash = hash("5u5234803riqifn"); ctx.response.set('X-Error-Hash', errorHash); ctx.throw(400, 'Invalid request body!'); } }); } }; };
额外说明
- 确保
process.env.ENC_KEY已正确配置,且长度符合AES-256要求(32字节) - 如果需要对响应体生成哈希,可在
await next()之后获取ctx.body并传入hash函数 - 全局中间件的执行顺序可在
./config/middlewares.js中调整位置,确保在合适时机运行
内容的提问来源于stack exchange,提问作者Saif Ali
相关产品推荐
相关产品推荐

