如何用ESLint要求res.[...].send(...)调用后添加return语句?
如何用ESLint规避HTTP响应头重复发送错误?
我们的部分Node.js控制器代码存在触发Error [ERR_HTTP_HEADERS_SENT]错误的风险,比如这段简化代码:
try{ if(someCheck) { res.status(400).send({someStatus}); } /* other code */ }catch(e){ res.status(500).send({error}); }
当someCheck条件触发400响应后,后续代码如果抛出异常,会进入catch块再次发送500响应,导致重复发送响应头,触发上述错误。
针对这个问题,可以通过ESLint规则强制要求调用send()后必须搭配return语句,既支持return res.status(400).send(...),也支持res.status(400).send(...); return;(后者更推荐),具体实现方式如下:
一、社区现成方案
部分第三方ESLint插件已包含类似规则,比如eslint-plugin-express中的相关约束,不过如果找不到完全匹配需求的,自定义规则会更贴合场景。
二、自定义ESLint规则
你可以自己编写ESLint规则,通过AST遍历检测res.send()调用,并强制要求后续添加return。
自定义规则示例
创建规则文件(比如eslint-rules/require-return-after-res-send.js):
module.exports = { meta: { type: "problem", docs: { description: "调用res.send()后必须添加return语句", category: "最佳实践", recommended: true }, fixable: null, schema: [] }, create: function(context) { return { CallExpression(node) { // 检测是否是res.send或链式调用的send(如res.status().send()) let isResSend = false; let currentNode = node; while (currentNode) { if (currentNode.type === 'MemberExpression' && currentNode.object?.type === 'Identifier' && currentNode.object.name === 'res') { if (currentNode.property.name === 'send') { isResSend = true; break; } } currentNode = currentNode.object; } if (!isResSend) return; // 检查是否已经在return语句中 let parent = node.parent; let isInReturn = false; while (parent) { if (parent.type === 'ReturnStatement') { isInReturn = true; break; } parent = parent.parent; } if (isInReturn) return; // 检查下一个语句是否是return const nextSibling = node.parent.nextSibling; if (nextSibling && nextSibling.type === 'ReturnStatement') return; // 抛出错误提示 context.report({ node: node, message: "调用res.send()后必须添加return语句,或直接return该调用结果" }); } }; } };
配置使用规则
在项目的.eslintrc.js中引入并启用该规则:
module.exports = { // ...其他ESLint配置 rules: { "./eslint-rules/require-return-after-res-send": "error" }, // 可仅在控制器文件中启用该规则 overrides: [ { files: ["**/*.controller.js"], rules: { "./eslint-rules/require-return-after-res-send": "error" } } ] };
配置完成后,ESLint会在检测到res.send()调用未搭配return时抛出错误,强制开发者修正代码,从根源上避免重复发送响应头的问题。
内容的提问来源于stack exchange,提问作者Jared
相关产品推荐
相关产品推荐

