Node.js 如何在中间件中读取流,并且在下一个中间件中仍然可以流化
我正在使用代理中间件将多部分数据转发到不同的端点。我希望使用前面的中间件从流中获得一些信息,并且仍然可以为下面的代理中间件读取流。是否存在允许我这样做的流模式Node.js 如何在中间件中读取流,并且在下一个中间件中仍然可以流化,node.js,express,stream,middleware,Node.js,Express,Stream,Middleware,我正在使用代理中间件将多部分数据转发到不同的端点。我希望使用前面的中间件从流中获得一些信息,并且仍然可以为下面的代理中间件读取流。是否存在允许我这样做的流模式 function preMiddleware(req, res, next) { req.rawBody = ''; req.on('data', function(chunk) { req.rawBody += chunk; }); req.on('end', () => { next();
function preMiddleware(req, res, next) {
req.rawBody = '';
req.on('data', function(chunk) {
req.rawBody += chunk;
});
req.on('end', () => {
next();
})
}
function proxyMiddleware(req, res, next) {
console.log(req.rawBody)
console.log(req.readable) // false
}
app.use('/cfs', preMiddleware, proxyMiddleware)
在将流式数据发送到外部端点之前,我想访问
的名称
值。我认为我需要这样做,因为端点将fee
解析为最终的url,我希望有一个句柄来进行一些后期处理。我愿意使用其他模式来解决这个问题。我认为没有任何机制可以在不从流中永久删除数据的情况下窥视流,也没有任何机制可以从流中“未读”数据以将其放回流中
因此,我可以想出一些可能的想法:
req
对象作为新流数据
事件处理程序,然后暂停流(注册数据甚至会自动触发流流动,您还不想让它流动),然后立即调用next()
。我认为这将允许您在代理中间件读取流时“查看”所有数据的副本,因为只有多个数据
事件处理程序,一个用于您的中间件,另一个用于代理中间件。这是一个理论上的想法——我还没有尝试过我不认为有任何机制可以在不从流中永久删除数据的情况下偷看流,也没有任何机制可以从流中“未读”数据以将其放回流中 因此,我可以想出一些可能的想法:
req
对象作为新流数据
事件处理程序,然后暂停流(注册数据甚至会自动触发流流动,您还不想让它流动),然后立即调用next()
。我认为这将允许您在代理中间件读取流时“查看”所有数据的副本,因为只有多个数据
事件处理程序,一个用于您的中间件,另一个用于代理中间件。这是一个理论上的想法——我还没有尝试过你需要能够向两个不同的方向发送一条流,如果你自己尝试的话,这并不容易——幸运的是,我在那天写了一个有用的模块 ,您可以使用它,我将使用它查找您感兴趣的数据 我假设您的数据将是一个多部分边界:
const {StringStream} = require('scramjet');
const {ReReadable} = require("rereadable-stream");
// I will use a single middleware, since express does not allow to pass an altered request object to next()
app.use('/cfs', (req, res, next) => {
const buffered = req.pipe(new ReReadable()); // rewind file to
let file = '';
buffered.pipe(new StringStream) // pipe to a StringStream
.lines('\n') // split request by line
.filter(x => x.startsWith('Content-Disposition: form-data;'))
// find form-data lines
.parse(x => x.split(/;\s*/).reduce((a, y) => { // split values
const z = y.split(/:\s*/); // split value name from value
a[z[0]] = JSON.parse(z[1]); // assign to accumulator (values are quoted)
return a;
}, {}))
.until(x => x.name === 'fee' && (file = x.filename, 1))
// run the stream until filename is found
.run()
.then(() => uploadFileToProxy(file, buffered.rewind(), res, next))
// upload the file using your method
});
您可能需要对其进行一些调整,以使其在真实场景中工作。如果您遇到问题或上面的答案中有问题需要解决,请告诉我。您需要能够向两个不同的方向发送单个流,如果您自己尝试,这并不容易-幸运的是,我在当天编写了一个有用的模块 ,您可以使用它,我将使用它查找您感兴趣的数据 我假设您的数据将是一个多部分边界:
const {StringStream} = require('scramjet');
const {ReReadable} = require("rereadable-stream");
// I will use a single middleware, since express does not allow to pass an altered request object to next()
app.use('/cfs', (req, res, next) => {
const buffered = req.pipe(new ReReadable()); // rewind file to
let file = '';
buffered.pipe(new StringStream) // pipe to a StringStream
.lines('\n') // split request by line
.filter(x => x.startsWith('Content-Disposition: form-data;'))
// find form-data lines
.parse(x => x.split(/;\s*/).reduce((a, y) => { // split values
const z = y.split(/:\s*/); // split value name from value
a[z[0]] = JSON.parse(z[1]); // assign to accumulator (values are quoted)
return a;
}, {}))
.until(x => x.name === 'fee' && (file = x.filename, 1))
// run the stream until filename is found
.run()
.then(() => uploadFileToProxy(file, buffered.rewind(), res, next))
// upload the file using your method
});
您可能需要对其进行一些调整,以使其在真实场景中工作。如果您遇到问题或上述答案中有问题需要解决,请告诉我。我认为您无法“未读”流。您可以将数据放在另一个流中,让下游中间件从另一个流访问数据,不过在这一点上,您也可以让下游中间件访问解析后的数据。如果您告诉我们您试图解决的真正问题,这可能会有所帮助,因为可能还有其他方法。在@jfriend00的评论中添加,一个可能的替代方案是@jfriend00,我已经更新了我的帖子。谢谢请评论任何不清楚的地方。我不认为你可以“未读”流。您可以将数据放在另一个流中,让下游中间件从另一个流访问数据,不过在这一点上,您也可以让下游中间件访问解析后的数据。如果您告诉我们您试图解决的真正问题,这可能会有所帮助,因为可能还有其他方法。在@jfriend00的评论中添加,一个可能的替代方案是@jfriend00,我已经更新了我的帖子。谢谢请评论任何不清楚的地方。