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.