【问题标题】:Handling bad JSON.parse() in node safely安全地处理节点中的错误 JSON.parse()
【发布时间】:2015-06-30 03:12:12
【问题描述】:

使用节点/快递 - 我想从请求标头中获取一些 JSON,但我想安全地做到这一点。
如果由于某种原因它不是有效的 JSON,那很好,它可以返回 false 或其他什么,它只会拒绝请求并继续。问题是如果它不是有效的 JSON,它会引发语法错误。通常我希望出现语法错误,但在这种情况下不会。

var boom = JSON.parse(req.headers.myHeader);

我是否从该特定模块刮取堆栈并检查是否存在错误的解析调用,如果是这种情况,它会忽略它吗?这似乎有点疯狂。肯定有更好的方法。

编辑: 我知道 try/catch 块是处理此错误的 A 方式,但它是节点应用程序中的最佳方式吗?这种方式会阻塞节点吗?

【问题讨论】:

标签: javascript json node.js express


【解决方案1】:

您可以使用trycatch

function parseMyHeader(){
    try {
      return JSON.parse(req.headers.myHeader);
    } catch(ex){
      return null;
    }
}

【讨论】:

  • 您也可以返回null(计算结果为假),以便解析
  • 你完全正确。当然你应该返回 null!
  • 因为 JSON.parse() 永远不会返回 undefined,也许在解析错误时返回 undefined 可能有助于识别解析错误
【解决方案2】:

标准的 try/catch 是在 node.js 中处理 JSON.parse 错误的正确方法,正如 Joyent 网站的节点 production practices for error handling 文档中所提到的那样:

...使用 try/catch 的唯一常用情况是 JSON.parse 和其他用户输入验证功能。

这也与 Aleksandr 在评论中提供的 nodejitsu 链接一致。

【讨论】:

    【解决方案3】:

    捕获无效 JSON 解析错误的最佳方法是将对 JSON.parse() 的调用放到 try/catch 块中。

    您确实没有任何其他选择 - 内置实现会在无效 JSON 数据上引发异常,防止该异常停止您的应用程序的唯一方法是捕获它。即使使用第 3 方库也无法避免这种情况 - 他们必须在某处拨打 JSON.parse() 时拨打 try/catch

    唯一的选择是实现您自己的 JSON 解析算法,该算法可能对无效数据结构更宽容,但这感觉就像用小核弹挖一个 1 立方米的洞。

    关于性能的说明

    Node.js cannot optimise 函数使用的 v8 JavaScript 引擎包含一个 try/catch 块。

    更新: v8 4.5 and above can optimise try/catch。对于旧版本,请参见下文。

    一个简单的解决方法是将安全解析逻辑放入一个单独的函数中,以便仍然可以优化主函数:

    function safelyParseJSON (json) {
      // This function cannot be optimised, it's best to
      // keep it small!
      var parsed
    
      try {
        parsed = JSON.parse(json)
      } catch (e) {
        // Oh well, but whatever...
      }
    
      return parsed // Could be undefined!
    }
    
    function doAlotOfStuff () {
      // ... stuff stuff stuff
      var json = safelyParseJSON(data)
      // Tadaa, I just got rid of an optimisation killer!
    }
    

    如果偶尔进行 JSON 解析,这可能不会对性能产生明显影响,但如果在使用量大的函数中使用不当,可能会导致响应时间急剧增加。

    关于 try/catch 被阻塞的注意事项

    需要注意的是,Node.js 中的 every.single.statement 的 JavaScript 代码一次只执行一次,无论是从主函数调用还是从回调或来自不同的模块或其他。因此,每一条语句都会阻塞该过程。这不一定是坏事——一个设计良好的应用程序将花费大部分时间等待外部资源(数据库响应、HTTP 通信、文件系统操作等)。因此,非常重要的是 v8 引擎可以优化频繁执行的 JavaScript 代码,以便在这种阻塞状态下花费尽可能少的时间 - 请参阅有关性能的说明。

    【讨论】:

    • 感谢您提供这个非常简洁且写得很好的答案,特别是关于优化的一点。
    • 为什么“1”可以解析json?
    • 为了完整起见,需要注意的是,自从引入 TurboFan 编译器以来,V8 现在对 try-catch 进行了优化。 news.ycombinator.com/item?id=12178856
    【解决方案4】:
            var parsed;
    
            try {
                parsed = JSON.parse(data);
            } catch (e) {
                parsed = JSON.parse(JSON.stringify(data));
            }
    
            root = parsed;
    

    这对我有用。 在 Catch 中,我在将数据解析为 JSON 之前将其转换为字符串化。

    【讨论】:

      【解决方案5】:

      这是关于如何在异常期间不中断脚本

      Promise.resolve((body)=>{
                  let fbResponse = JSON.parse(body);
                  // some code for good
              }).catch(error => {
                  cl('Parsing error:');
                  cl(error);
                  // some code for bad
              });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-08-08
        • 2016-08-30
        • 2018-07-26
        • 2017-09-06
        • 2022-12-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多