Node.js POST请求异常:ERR_HTTP_HEADERS_SENT及响应问题
解决WhatsApp API项目POST请求异常及ERR_HTTP_HEADERS_SENT错误
问题背景
开发基于WhatsApp API的项目,从机器人功能扩展为支持人工客服的前端系统,部署在fly.io上:
- GET请求正常返回结果
- POST请求存在异常:用Postman发送POST请求到
https://----.fly.dev/whatsapp/api/sendmessage时,WhatsApp能收到消息,但触发ERR_HTTP_HEADERS_SENT错误,服务进程退出 - 浏览器访问
https://----.fly.dev/whatsapp/messages无数据,直接访问POST路由提示Cannot GET /whatsapp/api/sendmessage
相关代码如下:
前端发送请求代码
async function sendTextFront(textResponse, number){ const data = JSON.stringify({ "messaging_product": "whatsapp", "recipient_type": "individual", "to": number, "type": "text", "text": { "preview_url": true, "body": textResponse } }) whatsappService.SendMessageWhatsApp(data); await makeRequest(data); return Promise.resolve(data); }; async function makeRequest(data) { let config = { method: 'post', maxBodyLength: Infinity, url: 'https://***.fly.dev/whatsapp/api/sendmessage', headers: { 'Content-Type': 'application/json', }, data : data }; try { const response = await axios.request(config); console.log(JSON.stringify(response.data)); } catch (e) { console.log(e); } }
后端路由配置
.post(`/api/sendmessage`, (req, res) => { const dat = whatsappController.send(req, res) if (dat) { res.status(200).json({ success: true, data: datos, }); } else { res.status(500).json({ success: false, error: "Error to send the message", }); console.log(dat); } })
后端入口文件配置
const appname = process.env.FLY_APP_NAME; const app = express(); const PORT = process.env.PORT || 8080 const HOST = "0.0.0.0"; app.use(express.json()); app.use("/whatsapp", apiRoute); app.listen(PORT, HOST, () => (console.log(`Server listen in port: ${PORT} and Host in: ${HOST}`))); console.log(`Back end in: https://${appname}.fly.dev/whatsapp/messages`);
fly.io错误日志
gru [info] node:internal/errors:491 gru [info] ErrorCaptureStackTrace(err); gru [info] ^ gru [info] Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client gru [info] at new NodeError (node:internal/errors:400:5) gru [info] at ServerResponse.setHeader (node:_http_outgoing:663:11) gru [info] at ServerResponse.header (/app/node_modules/express/lib/response.js:794:10) gru [info] at ServerResponse.send (/app/node_modules/express/lib/response.js:174:12) gru [info] at ServerResponse.json (/app/node_modules/express/lib/response.js:278:15) gru [info] at Object.send (/app/src/controllers/whatsappControllers.js:81:25) gru [info] at process.processTicksAndRejections (node:internal/process/task_queues:95:5) { gru [info] code: 'ERR_HTTP_HEADERS_SENT' gru [info] } gru [info] Node.js v18.13.0 gru [info] INFO Main child exited normally with code: 1 gru [info] INFO Starting clean up. gru [info] WARN hallpass exited, pid: 238, status: signal: 15 (SIGTERM)
错误原因分析
- ERR_HTTP_HEADERS_SENT核心原因:代码中重复发送HTTP响应。具体是
whatsappController.send(req, res)方法可能已经调用res.json()或res.send()发送了响应,之后路由又再次调用res.status().json(),尝试给同一个请求发送第二次响应,触发Node.js错误。 - 路由异步处理错误:如果
whatsappController.send是异步函数,直接赋值给dat会得到Promise对象而非实际返回值,导致if (dat)判断逻辑失效,加剧重复响应问题。 - 其他问题:
makeRequest中传递的data是手动JSON.stringify后的字符串,配合Content-Type: application/json会导致axios重复序列化,可能引发格式异常。- 浏览器直接访问POST路由提示
Cannot GET是正常行为,该路由仅支持POST请求。 /whatsapp/messages无数据需检查对应GET路由的实现(未提供该部分代码)。
修复步骤
1. 修复后端路由的异步处理与重复响应
修改路由为异步函数,确保只发送一次响应:
.post(`/api/sendmessage`, async (req, res) => { try { // 假设控制器send方法返回处理后的数据,由路由统一发送响应 const dat = await whatsappController.send(req); res.status(200).json({ success: true, data: dat, // 修正原代码拼写错误:datos -> dat }); } catch (error) { res.status(500).json({ success: false, error: "Error to send the message", }); console.error(error); } })
2. 调整控制器send方法
二选一:要么返回数据由路由发送响应,要么自己发送响应但不再让路由处理。
方案一:控制器返回数据,路由处理响应
// whatsappControllers.js中的send方法 async function send(req) { const result = await whatsappService.SendMessageWhatsApp(req.body); return result; }
方案二:控制器直接发送响应
// 路由简化为 .post(`/api/sendmessage`, (req, res) => { whatsappController.send(req, res); }) // 控制器send方法 async function send(req, res) { try { const result = await whatsappService.SendMessageWhatsApp(req.body); res.status(200).json({ success: true, data: result }); } catch (error) { res.status(500).json({ success: false, error: "Error to send the message" }); console.error(error); } }
3. 修复前端数据序列化问题
去掉手动JSON.stringify,直接传递对象,axios会自动处理序列化:
async function sendTextFront(textResponse, number){ const data = { "messaging_product": "whatsapp", "recipient_type": "individual", "to": number, "type": "text", "text": { "preview_url": true, "body": textResponse } }; // 注意:原代码同时调用两个发送方法会导致重复发消息,按需保留一个 // whatsappService.SendMessageWhatsApp(data); await makeRequest(data); return data; }; async function makeRequest(data) { let config = { method: 'post', maxBodyLength: Infinity, url: 'https://***.fly.dev/whatsapp/api/sendmessage', headers: { 'Content-Type': 'application/json', }, data : data }; try { const response = await axios.request(config); console.log(JSON.stringify(response.data)); } catch (e) { console.error(e); } }
4. 排查/whatsapp/messages无数据问题
检查对应GET路由的控制器:
- 确保正确查询并返回数据
- 确保调用
res.json()发送响应 - 查看fly.io日志中该路由的报错信息
额外说明
- 浏览器直接访问POST路由提示
Cannot GET是正常行为,若需支持GET请求,需添加对应路由配置。 - 修复后重新部署到fly.io,确认日志中无
ERR_HTTP_HEADERS_SENT错误。
内容的提问来源于stack exchange,提问作者TyRex
相关产品推荐
相关产品推荐

