Node Express/Request:如何使用body parsing来传输POST请求

8
我正试图按照以下方式将请求传输到远程服务器进行处理:

我正在尝试通过管道将请求传输到远程服务器进行处理,具体如下:

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

这对于GET请求非常有效。但是对于POST请求,我遇到了困难。我认为需要注意的一个重要点是,在POST请求之前,我使用了一个body parser来从POST请求中提取body...它只是一个基本的文本body parser,因为body包含纯文本:

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

根据这个问题这个问题,在将POST请求进行任何处理之前进行处理会导致问题。实际上,当我删除解析器时,管道似乎可以正常工作。
问题在于我需要先检查主体,进行一些初始处理,然后确定是否根本需要将请求管道传输到远程服务器。因此,我需要在管道之前解析主体。
有没有解决这个问题的方法?
3个回答

16
问题在于使用流(如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]);

向大师学习!天才!不仅提供了一个很好的解决方案,还清晰简洁地解释了问题发生的原因。@robertklep,您确实是大师! - drmrbrewer
只有一件事...它应该是request.post(url)而不仅仅是request(url)吗? - drmrbrewer
1
我非常确定request将使用req.method/stream.method来确定要执行的请求类型,因此您不必明确指定它。 - robertklep
1
我似乎无法使用into-stream(在版本为6.14的节点上,我可以使用另一个第三方替代品吗?还有其他选项吗?) - Omri Shneor
@OmriShneor into stream 是一个在 npm 上的包 https://www.npmjs.com/package/into-stream - Peter Moses

1
如果解析器出现问题,您应该创建自己的中间件。老实说,您可能希望以不同于body parser的方式解析主体。鉴于我们对项目其他部分的了解有限,您可以创建一个中间件来钩取body parser中间件,然后只发送请求的克隆。但是这并不是很有效,但会起作用,并可能帮助您找到正确的方向。
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]);

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


-1
需要通过POST发送大量数据,但是我一直收到“Error: socket hang up / code: 'ECONNRESET'”错误提示。通过增加body parser的限制来解决这个问题。
var bodyParser = require('body-parser'); app.use(bodyParser.urlencoded({extended: true})); app.use(bodyParser.json({limit:'50mb'}));

这如何回答问题?请确保您的回答与所问问题相关。 - Peter Moses

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接