1

I am trying to create a simple express middleware filter which should look at the POST body and determine if it should be piped to the correct server, or blocked. If I use body-parser it appears that I do get the req.body available to me, but it disappears from the request when I pipe the request to another external server.

The way I have tried to solve this is the following:

//Router
router.route('')
    .post(authController.isAuthenticated,
        urlHelper.bodyParser,             //Without these two, everything pipes correctly
        urlHelper.filterBasedOnSomething, //Without these two, everything pipes correctly
        urlHelper.pipeToTrustedZone);

In urlHelper:

const filterBasedOnSomething = function (req, res, next) {
        if (req.body
            && req.body.something === 'some string'
            && req.body.somethingElse === 'some other value') {
            return res.status(403).send("You shall not pass");
        } else {
            next();
        }
    }
const pipeToTrustedZone = function (req, res) {
        //Here we are figuring out the correct forwarding url. This is simplified a little for the question, but it is well tested and works.
        var url = getProxiedPath(req.baseUrl) + req.originalUrl;
        req.pipe(request({ qs: req.query, uri: url }).on('error', function (err) {
            log.info(err);
            return res.sendStatus(400);
        }))
            .pipe(res);

};
module.exports = {
  bodyParser: require('body-parser').json(),
  filterBasedOnSomething: filterBasedOnSomething,
  pipeToTrustedZone: pipeToTrustedZone,
  //..
}

This seem to give me the req.body in my filter-method, but the body is consumed and is not received after it has been piped forward. I have tried multiple things, like req.emit('data', JSON.stringify(req.body)); and req.write(.., but it all seem to fail.

Is there a way for me to look at the request body before piping it further without deleting it? Or is there an inherit problem with my approach?

I have found multiple github issues and SO questions relating to this, but I haven't been successful in getting any of those approaches to work.:

https://github.com/expressjs/body-parser/issues/74

Writing express middleware to get raw request body before body-parser

https://github.com/expressjs/body-parser/issues/94

4

1 回答 1

1

有没有办法让我在进一步管道之前查看请求正文而不删除它?还是我的方法存在继承问题?

固有的问题是你想先读取一个流,然后再通过管道传输它——即使流已经被读取并且它已经消失了。

您需要做的是在读取流时缓存流,以便以后可以通过管道传输,或者从 body-parser 的输出重构主体。

但是您不能倒带流并再次开始读取它,因为这意味着将所有流事件记录在内存中,而使用流的通常优点是您不需要将所有内容都记录在内存中,您只需data在一次。

如果您是否要通过管道传输流的决定可以基于主体外部的数据(例如路径或某些标头等),那么您可以仅将主体解析器中间件用于那些未通过管道传输的情况.

但是,如果决定是基于正文的实际内容,就像您的示例中的情况一样,那么您别无选择,只能先阅读它 - 此时无法再次阅读它。

有几个模块可以帮助您:

但你可能会更好地从 body-parser 的解析输出中重建 body,如下所示:

request({ qs: req.query, uri: url, body: req.body, json: true })

并仅管道响应。

于 2017-06-06T15:14:06.397 回答