Consider the following rather trivial middleware:
(req, res, next) => {
const stream = fs.createReadStream(req.filePath)
await new Promise((resolve, reject) => stream
.on('error', reject)
.on('end', resolve)
.pipe(res, { end: false })
.on('error', reject)
// 'close' is emitted if client prematurely disconnects.
.on('close', resolve)
res.end()
}
There are a few problems which I am unsure how to handle:
close
or error
how is the source stream cleaned up? autoClose
will only run on end
which will only run if all data has been read. However, if the target fails how is that propagated to the source? Should I always call destroy
on the source stream?This seems to do the trick:
import onFinished from 'on-finished'
(req, res, next) => {
const stream = fs.createReadStream(req.filePath)
onFinished(res, () => stream.destroy && stream.destroy())
if (onFinished.isFinished(res)) {
return
}
await new Promise((resolve, reject) => stream
.on('error', reject)
.on('end', resolve)
.pipe(res, { end: false })
.on('error', reject)
// 'close' is emitted if client prematurely disconnects.
.on('close', resolve)
res.end()
}