【问题标题】:Node.js - Handle body-parser invalid JSON errorNode.js - 处理正文解析器无效的 JSON 错误
【发布时间】:2019-04-02 13:41:22
【问题描述】:

我正在像这样使用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 })); 

当收到像{ "foo": "bar" } 这样的有效输入时,一切正常,我可以使用req.body 访问已解析的对象。

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

data: JSON.stringify("just something inappropriate"),

我收到此错误:

{ 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 ...

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

【问题讨论】:

标签: javascript node.js express error-handling body-parser


【解决方案1】:

body-parser 会引发多种错误。它们涉及发送错误的标头或不被它接受的数据,或者在读取所有数据之前取消请求。

如果您想要涵盖所有这些错误(包括您提到的错误)的强大解决方案,请使用此中间件

https://www.npmjs.com/package/express-body-parser-error-handler

$ npm i express-body-parser-error-handler

并在你的 body-parser 初始化之后放置它

用法示例:

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(urlencoded({extended: false, limit: defaultLimitSize}));
app.use('/', json({limit: '250'}));

// body parser error handler
app.use(bodyParserErrorHandler());
app.use(router);
...

【讨论】:

    【解决方案2】:

    我回答这个问题可能为时已晚,但我先放在这里。 我也收到了这些错误,例如:

    SyntaxError: Unexpected token / in JSON at position 11
    

    我发现当我请求json时像

    {    
        //"name":"Tanjiro",
        "username":"tan_jiro",
        "password":"tan@jiro"
    }
    

    只有这样它才给我这个错误。如果我要求只使用,

    {    
        "username":"tan_jiro",
        "password":"tan@jiro"
    }
    

    它没有给我任何错误。所以看起来错误在于请求是如何完成的,而不是 bodyparser.json()。 谢谢。

    【讨论】:

      【解决方案3】:

      从 Express 4.16.0 开始 - 发布日期:2017-09-28,您可以捕获来自不同中间件的不同错误,将错误处理程序拆分为不同的函数,而无需使用已弃用的 Bodyparser。

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

      Express 4.16.0 及更高版本的代码中的注意事项:

       app.use(express.json()); // Without middleware error handling.
      

      替换bodyParser:

       app.use(bodyParser.json()); // Without middleware error handling.
      

      【讨论】:

        【解决方案4】:

        一种选择是添加自定义 error handler middleware 并添加一个检查以捕获类似的 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();
        });
        

        另一种选择是包装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();
            });
        });
        

        或者如果你想重用这个功能来捕捉来自不同中间件的不同错误,你可以这样做:

        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();
        }));
        

        【讨论】:

        • 请注意,第二个选项也适用于较新的 express.json()
        【解决方案5】:

        添加一个错误处理程序,然后自定义处理该错误的默认方式的行为,默认情况下会按照您的描述崩溃。

        app.use((err, req, res, callback) => {
          // todo: implement error handling logic and return an appropriate response
          console.error(err)
          res.send(500)
          callback()
        })
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-01-06
          • 2020-12-15
          • 2011-05-28
          • 2012-06-11
          • 1970-01-01
          • 1970-01-01
          • 2015-03-12
          • 2012-12-13
          相关资源
          最近更新 更多