Node.js-处理正文解析器无效的JSON错误

Raz*_*Raz 2 javascript error-handling node.js express body-parser

我正在使用body-parser像这样的包:

// For parsing application/json:
app.use(require('body-parser').json());

// For parsing application/x-www-form-urlencoded
app.use(require('body-parser').urlencoded({ extended: true })); 
Run Code Online (Sandbox Code Playgroud)

{ "foo": "bar" }收到类似有效的输入后, 一切正常,我可以使用来访问已解析的对象req.body

但是,当发送无效(非JSON)数据时:

data: JSON.stringify("just something inappropriate"),
Run Code Online (Sandbox Code Playgroud)

我收到此错误:

{ SyntaxError: Unexpected token " in JSON at position 0
    at JSON.parse (<anonymous>)
    at createStrictSyntaxError
    at ...
expose: true,
statusCode: 400,
status: 400,
body: '"Something"',
type: 'entity.parse.failed' }

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client at ...
Run Code Online (Sandbox Code Playgroud)

我该如何正确处理以防止服务器关闭?

Dan*_*ger 5

一种选择是添加自定义错误处理程序中间件,并添加检查以捕获像这样的JSON解析错误:

app.use(require('body-parser').json()); 
app.use(require('body-parser').urlencoded({ extended: true }));

...

app.use((err, req, res, next) => {
    // This check makes sure this is a JSON parsing issue, but it might be
    // coming from any middleware, not just body-parser:

    if (err instanceof SyntaxError && err.status === 400 && 'body' in err) {
        console.error(err);
        return res.sendStatus(400); // Bad request
    }

    next();
});
Run Code Online (Sandbox Code Playgroud)

另一个选择是包装body-parser的中间件以捕获仅来自那里的错误:

const bodyParser = require('body-parser');

app.use((req, res, next) => {
    bodyParser.json()(req, res, err => {
        if (err) {
            console.error(err);
            return res.sendStatus(400); // Bad request
        }

        next();
    });
});
Run Code Online (Sandbox Code Playgroud)

或者,如果您想重用此功能以捕获来自不同中间件的不同错误,则可以执行以下操作:

function handleError(middleware, errorHandler) {
    middleware(req, res, err => err ? errorHandler(err, req, res, next) : next());
}

const bodyParser = require('body-parser');

app.use(handleError(bodyParser.json(), (err, req, res, next) => {
    if (err) {
        console.error(err);
        return res.sendStatus(400); // Bad request
    }

    next();
}));
Run Code Online (Sandbox Code Playgroud)

  • 请注意,第二个选项也适用于较新的“express.json()”。 (2认同)