2017-06-15 88 views
1

我试图管,用于由远程服务器处理,大意如下的请求POST请求:节点快递/要求:管道与身体解析

var destination = request(url); 
req.pipe(destination).pipe(res); 

这只是正常的GET请求。但是对于POST请求我很挣扎。我认为需要注意的一点是,对于POST请求,我在我的POST路由处理程序之前使用了一个body解析器,以便从POST请求中提取正文...这只是一个基本的文本正文解析器,因为正文包含纯文本:

var postRouteHandler = someFunction; 
var bodyParser = require('body-parser'); 
var textParser = bodyParser.text({ 
    limit: '50kb' 
}); 
app.use('/postRoute', [textParser, postRouteHandler]); 

this issuethis issue在我看来,关于POST要求做任何处理,你管的时候,才导致出现问题。事实上,当我删除解析器时,管道似乎工作正常。

问题是我需要首先检查身体,进行一些初始处理,然后确定是否将请求传送到远程服务器。所以我需要来解析管道之前的身体。

有没有办法解决这个问题?

回答

6

问题在于,对于流(如req),一旦阅读完它就无法重置它。

由于body-parser已经读取了流,管道将无法工作,因为它会尝试再次读取流(此时已耗尽)。

一种解决方法是采取由body-parser阅读文本,并且为了创建一个最小req“克隆”为request能够沿着传递请求:

var intoStream = require('into-stream'); 
var bodyParser = require('body-parser'); 
var textParser = bodyParser.text({ limit: '50kb' }); 

var postRouteHandler = function(req, res) { 
    let text = req.body; 
    if (! shouldPipe(text)) { 
    return res.sendStatus(400); // or whatever 
    } 

    // Here's where the magic happens: create a new stream from `text`, 
    // and copy the properties from `req` that `request` needs to pass 
    // along the request to the destination. 
    let stream  = intoStream(text); 
    stream.method = req.method; 
    stream.headers = req.headers; 

    // Pipe the newly created stream to request. 
    stream.pipe(request(url)).pipe(res); 
}; 
app.use('/postRoute', [textParser, postRouteHandler]); 
+0

向大师学习!天才!这不仅是一个很好的解决方案,也是对问题发生原因的一个清晰而简洁的解释。你确实是大师@robertklep! – drmrbrewer

+0

...只是一件事......它应该是'request.post(url)'而不是'request(url)'? – drmrbrewer

+0

我非常肯定'request'将使用'req.method/stream.method'来确定执行的请求类型,因此您不必明确说明它。 – robertklep

1

如果解析器导致问题,您应该创建自己的中间件。诚实地说,你可能想要以与解析器不同的方式解析身体。

鉴于您对项目其余部分的工作知识有限,您可以创建中间件来挂钩正文解析器中间件,并发送请求克隆。然而,这不是非常有效,但会起作用,并可能有助于指引您朝着正确的方向发展。

var postRouteHandler = someFunction; 
var bodyParser = require('body-parser'); 
var textParseMiddleware = function (req, res, next) { 

    var requestclone = _.clone(req); 
    var textParser = bodyParser.text({ 
    limit: '50kb' 
    }); 

    textParser(requestclone, res, function(){ 
    console.log('examine the body here', requestclone.body); 
    }); 


} 

app.use('/postRoute', [textParserMiddleWare, postRouteHandler]); 

我还没有测试过上面的代码。

0

需要发送一个巨大的大数据通过POST,我得到错误:套接字挂断/代码:'ECONNRESET'。 能够通过增加对主体解析器的限制来解决它。

var bodyParser = require('body-parser'); app.use(bodyParser.urlencoded({extended: true})); app.use(bodyParser.json({limit:'50mb'}));