向UploadFxPLink传附件遇ERR_HTTP_HEADERS_SENT错误求助
错误排查与解决方案
错误信息
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client at new NodeError (node:internal/errors:399:5) at ServerResponse.setHeader (node:_http_outgoing:645:11) at ServerResponse.header (D:\NIDC\BL1\node_modules\express\lib\response.js:771:10) at ServerResponse.send (D:\NIDC\BL1\node_modules\express\lib\response.js:170:12) at ServerResponse.json (D:\NIDC\BL1\node_modules\express\lib\response.js:267:15) at ServerResponse.send (D:\NIDC\BL1\node_modules\express\lib\response.js:158:21) at Request._callback (D:\NIDC\BL1\ors.js:2848:11) at self.callback (D:\NIDC\BL1\node_modules\request\request.js:185:22) at Request.emit (node:events:513:28) at Request.onRequestError (D:\NIDC\BL1\node_modules\request\request.js:877:8) { code: 'ERR_HTTP_HEADERS_SENT' }
可能原因
- 路由重复注册:如果
app.post('/UploadFxP')被多次调用,同一个请求会触发多个回调,导致多次向客户端发送响应。 - 未终止else分支执行:
else块中的res.redirect('/')未添加return,后续若新增逻辑可能引发意外的重复响应。 - request库的潜在问题:request库已停止维护,存在回调异常触发或重复调用的已知问题。
- 未处理非成功API响应:当前代码仅处理请求错误,未校验API返回的状态码(如4xx、5xx),可能引发后续逻辑异常。
解决方案
1. 检查路由注册
确认app.post('/UploadFxP')在项目中仅被注册一次,避免同一个请求触发多个回调。
2. 终止else分支执行
将else块代码修改为:
else { return res.redirect('/'); }
明确终止函数执行,防止后续代码意外发送响应。
3. 替换request库(推荐)
使用维护中的axios库替代已废弃的request,示例代码如下:
const axios = require('axios'); app.post('/UploadFxP', async function (req, res) { const trackngNo = req.session.TrackingNo; const attachmentId = req.body.attachmentId; const trackNo = req.body.trackNo; const userId = req.session.userID; const token = req.session.token; const atachment = req.body.atachment; const attachment = atachment.replace("data:application/pdf;base64,", ""); console.log('trackingNo: ', trackngNo) if (req.session.userID) { try { const response = await axios.post(UploadFxPLink, { trackNo, trackngNo, userId, attachmentId, attachment, // 修正原代码拼写错误 token }, { headers: { 'Authorization': `Bearer ${token}` } }); return res.send({ "success": "success" }); } catch (error) { console.log("Failed to UploadFxP " + error); return res.send({ "failed": "failed" }); } } else { return res.redirect('/'); } });
4. 完善原request代码的错误处理
若暂时不替换库,可添加响应状态校验与已发送响应检查:
app.post('/UploadFxP', function (req, res) { var trackngNo = req.session.TrackingNo; var attachmentId = req.body.attachmentId; var trackNo = req.body.trackNo; var userId = req.session.userID; var token = req.session.token; var atachment = req.body.atachment; var attachment = atachment.replace("data:application/pdf;base64,", ""); console.log('trackingNo: ', trackngNo) if (req.session.userID) { request({ url: UploadFxPLink, method: 'POST', json: { trackNo: trackNo, trackngNo: trackngNo, userId: userId, attachmentId: attachmentId, attachment: attachment, // 修正拼写错误 token: token }, headers: { 'Authorization': `Bearer ${token}` } }, function (error, response, body) { // 避免重复发送响应 if (res.headersSent) return; if (error) { console.log("Failed to UploadFxP " + error); return res.send({ "failed": "failed" }); } // 校验API响应状态码 if (response.statusCode < 200 || response.statusCode >= 300) { console.log("API error status: " + response.statusCode); return res.send({ "failed": "API request failed" }); } return res.send({ "success": "success" }); }); } else { return res.redirect('/'); } });
5. 排查中间件冲突
检查该路由前后的中间件,确保没有其他中间件在路由处理完成后再次发送响应。
内容的提问来源于stack exchange,提问作者Ibrahimu Mwakipesile
相关产品推荐
相关产品推荐

