Node.js跨进程用Express发起POST请求时触发write after end错误
解决Node.js http.get发起POST请求时的Error [ERR_STREAM_WRITE_AFTER_END]错误
问题描述
Node.js登录进程调用另一个Node.js API进程时,其余流程正常,但使用http.get发起POST请求,执行request.write(body)语句时出现错误:Error [ERR_STREAM_WRITE_AFTER_END]: write after end。
相关代码
调用方代码
app.enable('strict routing'); app.disable('x-powered-by'); app.use(express.json()); app.use(express.urlencoded({ extended:true })); assert(hbs); app.set('view engine','hbs'); app.engine('hbs',hbs.create().__express) svr.server = http.createServer(app) app.get('/',function(req,res,next) { res.render("login.hbs") }) app.post('/login', async function(req,res) { console.log("post login",req.body) const password = req.body.password console.log('password',password) const body = JSON.stringify({ appid:appid, authtoken:authtoken, password:password }) const options = { host: api.host, port: api.port, path: '/api/login', method: "POST", headers: { 'Content-Type':'application/json', 'Content-Length':Buffer.byteLength(body) }, } console.log('options',options) // var data = '' var request = http.get(options, function(res) { let data = '' res.setEncoding('utf8') res.on('data',function(chunk) { data += chunk }) res.on('end',function() { console.log('data',JSON.parse(data)) }) res.on('error',function(e) { console.log('err',e.toString()) }) }) request.write(body) request.end() res.end() }) app.listen(svr.port,svr.host,function() { console.log('http listen',svr.port,svr.host) })
被调用方代码
app.enable('strict routing'); app.disable('x-powered-by'); app.use(express.json()) app.use(express.urlencoded({ extended:true })) svr.server = http.createServer(app) app.get('*', async function(req,res,next) { console.log('all') next() }) app.post('/api/login', async function(req,res) { console.log("post api login",req.body) const account = '' res.status(200).json({ account:account, session:uuid.v4() }) // res.status(400).json({ error:'server error message' }) }) app.listen(svr.port,svr.host,function() { console.log('http listen',svr.port,svr.host) })
解决方案
核心问题
http.get是http.request的封装方法,它会自动调用request.end()来结束请求流,因此当你手动调用request.write(body)和request.end()时,请求流已经被关闭,从而触发write after end错误。
修改后的调用方代码
将http.get替换为http.request,并完善响应和错误处理逻辑:
app.post('/login', async function(req,res) { console.log("post login",req.body) const password = req.body.password console.log('password',password) const body = JSON.stringify({ appid:appid, authtoken:authtoken, password:password }) const options = { host: api.host, port: api.port, path: '/api/login', method: "POST", headers: { 'Content-Type':'application/json', 'Content-Length':Buffer.byteLength(body) }, } console.log('options',options) var request = http.request(options, function(response) { let data = '' response.setEncoding('utf8') response.on('data',function(chunk) { data += chunk }) response.on('end',function() { console.log('data',JSON.parse(data)) // 等待API返回结果后,再给前端响应 res.end(JSON.stringify(JSON.parse(data))) }) response.on('error',function(e) { console.log('err',e.toString()) res.status(500).end(e.toString()) }) }) // 捕获请求自身的异常 request.on('error', function(e) { console.log('request error', e.toString()) res.status(500).end(e.toString()) }) request.write(body) request.end() })
额外优化说明
- 原代码中
res.end()直接返回空响应,修改后等待API调用完成再返回结果,避免前端提前收到无效响应。 - 添加
request对象的错误监听,覆盖请求发起阶段的异常场景。
内容的提问来源于stack exchange,提问作者Gilles
相关产品推荐
相关产品推荐

