Home > database >  Keep original content of request.body after express.urlencoded
Keep original content of request.body after express.urlencoded

Time:10-02

Is there a way to keep the original text of the request.body after it is passed through and parsed by request.urlecoded?

request.body at any handler after this middleware (app.use(express.urlencoded())) is an object and I can't find any way to get the original raw body that was POSTed to the server.

CodePudding user response:

The server can consume an incoming request only once, because the request body is streamed by the client and the HTTP protocol does not allow the server to request a "rewind" from the client. The express.urlencoded middleware parses the request into an object and express.text parses it into a string. In order to execute both in parallel, you need a "duplexer" that pipes the incoming stream into two streams, one for each middleware to parse.

app.use(function(req, res, next) {
  var url = new stream.PassThrough();
  url.headers = {
    "content-length": req.get("content-length"),
    "content-type": req.get("content-type")
  };
  var text = new stream.PassThrough();
  text.headers = {
    "content-length": req.get("content-length"),
    "content-type": "text/plain"
  };
  req.pipe(new stream.Writable({
    write(chunk, encoding, callback) {
      url.push(chunk);
      text.push(chunk);
      callback();
    },
    destroy(err, callback) {
      url.destroy(err);
      text.destroy(err);
      callback();
    },
    final(callback) {
      url.push(null);
      text.push(null);
      callback();
    }
  }));
  Promise.all([
    new Promise(function(resolve, reject) {
      express.urlencoded({extended: false})(url, res, function() {
        resolve(url.body);
      });
    }),
    new Promise(function(resolve, reject) {
      express.text()(text, res, function() {
        resolve(text.body);
      });
    })
  ]).then(function([urlBody, textBody]) {
    req.urlBody = urlBody;  // parsed into an object
    req.textBody = textBody;  // parsed as the original string
    next();
  });
});

Addendum

After reading the express.urlencoded documentation, I found a simpler solution:

app.use(express.urlencoded({extended: false,
  verify: function(req, res, buf, encoding) {
    req.textBody = buf.toString(encoding);
  }
}));

This makes req.body an object (as usual) and additionally writes the original into req.textBody. But I hope my first attempt is still instructive.

  • Related