NodeJS服务器挂起流错误



我有一个NodeJS脚本,我从请求中通过管道传输流->响应

const { createServer } = require('http')
const { Client } = require('undici')
const { pipeline, Transform, PassThrough } = require('stream')
const server = createServer((req, res) => {
const url = new URL('http://localhost:8000/resource/testing')
const client = new Client(url.origin)
pipeline(
req,
new Transform({
decodeStrings: false,
transform (chunk, encoding, callback) {
callback(new Error('test error'))
},
}),
client.pipeline(
{
path: url.pathname + url.search,
method: 'GET',
},
({ statusCode, headers, body }) => {
res.writeHead(statusCode)
return pipeline(body, new PassThrough(), () => {})
}
),
err => {
if (err) {
console.error(err)
res.writeHead(500, {
'content-type': 'text/plain; charset=UTF-8'
})
res.write(JSON.stringify({
status: 'failed',
error: 'Server exception occurred while handling request'
}))
res.end()
}
client.close()
}
)
});
server.listen(process.env.PORT || 3000, '0.0.0.0', () => {
console.log(`Server listening at http://${server.address().address}:${server.address().port}`)
})

现在,在这个场景中,我只是模拟一个错误,因为对于成功来说,它是有效的。所以问题是,每当我用命令(例如curl -X POST -d '{"name": "john doe"}' -H 'Content-Type: application/json' localhost:3000(测试这一点时,到达错误代码块,但请求在没有发送500错误的情况下终止,是不是我错过了什么,因为我已经在这方面花了很多时间,这让我疯狂地

附言:正如你所看到的,我用的是undici包装。

我找到了一个解决方案,并决定使用对我有效的解决方案,以防其他人遇到同样的情况,所以我基本上将reqres与管道隔离

const { createServer } = require('http')
const { Client } = require('undici')
const { pipeline, Transform, PassThrough, Writable, Readable } = require('stream')
const server = createServer((req, res) => {
const url = new URL('http://localhost:8000/resource/testing')
const writable = new Writable({
autoDestroy: false,
write(chunk, _, callback) {
res.write(chunk)
callback()
},
final(callback) {
res.end()
callback()
}
})
writable.on('error', err => {
console.log('writable err', err)
res.writeHead(500, {
'content-type': 'text/plain; charset=UTF-8'
})
res.write(JSON.stringify({
status: 'failed',
error: 'Server exception occurred while handling request'
}))
res.end()
})
const client = new Client(url.origin)
pipeline(
Readable.from(req),
new Transform({
decodeStrings: false,
transform (chunk, encoding, callback) {
callback(new Error('sample error'))
},
}),
client.pipeline(
{
path: url.pathname + url.search,
method: 'GET',
},
({ statusCode, headers, body }) => {
res.writeHead(statusCode)
return pipeline(body, new PassThrough(), () => {})
}
),
writable,
err => {
if (err) {
console.error(err)
}
client.close()
}
)
});
server.listen(process.env.PORT || 3000, '0.0.0.0', () => {
console.log(`Server listening at http://${server.address().address}:${server.address().port}`)
})

因此,通过这样做,我可以完全控制我将要处理的流,从而可以自由地捕捉个人错误。

p.S.pipeline在遇到错误时销毁所有流(调用stream.destroy(,在这种情况下,它对req和res对象都调用destroy方法,我花了一些时间才弄清楚。

最新更新