Catch express bodyParser error
Javascriptnode.jsExpressJavascript Problem Overview
I want to catch the error from the bodyParser() middleware when I send a json object and it is invalid because I want to send a custom response instead of a generic 400 error.
This is what I have and it works:
app.use (express.bodyParser ());
app.use (function (error, req, res, next){
//Catch bodyParser error
if (error.message === "invalid json"){
sendError (res, myCustomErrorMessage);
}else{
next ();
}
});
But this seems to me a very ugly approach because I'm comparing the error message which could change in future express versions. There's any other way to catch bodyParser() errors?
EDIT:
This is the error when the request body has an invalid json:
{
stack: 'Error: invalid json\n at Object.exports.error (<path>/node_modules/express/node_modules/connect/lib/utils.js:55:13)\n at IncomingMessage.<anonymous> (<path>/node_modules/express/node_modules/connect/lib/middleware/json.js:74:71)\n at IncomingMessage.EventEmitter.emit (events.js:92:17)\n at _stream_readable.js:872:14\n at process._tickDomainCallback (node.js:459:13)',
arguments: undefined,
type: undefined,
message: 'invalid json',
status: 400
}
Pretty printed stack:
Error: invalid json
at Object.exports.error (<path>/node_modules/express/node_modules/connect/lib/utils.js:55:13)
at IncomingMessage.<anonymous> (<path>/node_modules/express/node_modules/connect/lib/middleware/json.js:74:71)
at IncomingMessage.EventEmitter.emit (events.js:92:17)
at _stream_readable.js:872:14
at process._tickDomainCallback (node.js:459:13)
Javascript Solutions
Solution 1 - Javascript
I think your best bet is to check for SyntaxError
:
app.use(function (error, req, res, next) {
if (error instanceof SyntaxError) {
sendError(res, myCustomErrorMessage);
} else {
next();
}
});
Solution 2 - Javascript
From the answer of @alexander but with an example of usage
app.use((req, res, next) => {
bodyParser.json({
verify: addRawBody,
})(req, res, (err) => {
if (err) {
console.log(err);
res.sendStatus(400);
return;
}
next();
});
});
function addRawBody(req, res, buf, encoding) {
req.rawBody = buf.toString();
}
Solution 3 - Javascript
Ok, found it:
bodyParser() is a convenience function for json(), urlencoded() and multipart(). I just need to call to json(), catch the error and call to urlencoded() and multipart().
app.use (express.json ());
app.use (function (error, req, res, next){
//Catch json error
sendError (res, myCustomErrorMessage);
});
app.use (express.urlencoded ());
app.use (express.multipart ());
Solution 4 - Javascript
what I did was just:
app.use(bodyParser.json({ limit: '10mb' }))
// body parser error catcher
app.use((err, req, res, next) => {
if (err) {
res.status(400).send('error parsing data')
} else {
next()
}
})
Solution 5 - Javascript
All errors include a type property from 1.18.0 release onwards. For parse failure, err.type === 'entity.parse.failed'.
app.use(function (error, req, res, next) {
if (error.type === 'entity.parse.failed') {
sendError(res, myCustomErrorMessage);
} else {
next();
}
});
Solution 6 - Javascript
I found checking for SyntaxError
to be not enough, therefore I do:
if (err instanceof SyntaxError &&
err.status >= 400 && err.status < 500 &&
err.message.indexOf('JSON') !== -1) {
// process filtered exception here
}
Solution 7 - Javascript
create new module "hook-body-parser.js" hook everything with body parser over here
const bodyParser = require("body-parser");
module.exports = () => {
return [
(req, res, next) => {
bodyParser.json()(req, res, (error) => {
if (error instanceof SyntaxError) {
res.sendStatus(400);
} else {
next();
}
});
},
bodyParser.urlencoded({ extended: true }),
];
};
and use over express like this
... app.use(hookBodyParser()) ...
Solution 8 - Javascript
if you want to catch all errors thrown by body-parsr for example entity.too.large or encoding.unsupported
just place this middleware right after your body-parser initialization
$ npm i express-body-parser-error-handler
https://www.npmjs.com/package/express-body-parser-error-handler
for example:
const bodyParserErrorHandler = require('express-body-parser-error-handler')
const { urlencoded, json } = require('body-parser')
const express = require('express')
const app = express();
router.route('/').get(function (req, res) {
return res.json({message:"🚀"});
});
// body parser initilization
app.use('/', json({limit: '250'}));
// body parser error handler
app.use(bodyParserErrorHandler());
app.use(router);
...
Solution 9 - Javascript
(bodyParser, req, res) => new Promise((resolve, reject) => {
try {
bodyParser(req, res, err => {
if (err instanceof Error) {
reject(err);
} else {
resolve();
}
});
} catch (e) {
reject(e);
}
})
Bullet-proof. Future-aware. WTFPL-Licensed. And also useful w/ async/await.