欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

由“RangeError: Invalid status code: 0”错误所引发的思考

程序员文章站 2022-06-27 21:49:07
最近发现一个基于Node.js平台上的Express框架运行的Web网站经常报这样一个错误: 网站的源码中有专门针对错误处理的中间件,经过精简之后的代码如下: 乍一看,这里的status code不太可能为0,因为无论err.code的值为字符串0还是数字0,最终都会被赋值为500。除非err.co ......

  最近发现一个基于node.js平台上的express框架运行的web网站经常报这样一个错误:

rangeerror: invalid status code: 0

  网站的源码中有专门针对错误处理的中间件,经过精简之后的代码如下:

module.exports = function (err, req, res, next) {
  var _code = err.code || 500;
  if (_code < 100 || _code >= 600) {
    _code = 500;
  }
  var _finalerr = {statuscode: -1, message: '500 - 服务器内部错误', code: _code, err: err, error: true};

  res.status(_code);
  if (!res.headerssent) {
      res.json(_finalerr);
  }

  if (err) {
    next(err);
  }
};

  乍一看,这里的status code不太可能为0,因为无论err.code的值为字符串0还是数字0,最终都会被赋值为500。除非err.code的原始值是一个不能隐式转换成数字的字符串。为了进行验证,我们写了如下代码:

var _err = new error();
_err.code = "illegal http status code";
throw _err;

  启动webstorm进入调试模式,果然复现了本文开头给出的那个错误。

由“RangeError: Invalid status code: 0”错误所引发的思考

  那么问题来了,为什么给定的http status code是一个字符串,错误提示却显示这里的status code是0呢?为了搞清楚其中的原因,我们根据错误堆栈一层层查找源码。该错误的最终出处是在node.js源码的_http_server.js文件的writehead函数中,核心部分的代码如下:

statuscode |= 0;
if (statuscode < 100 || statuscode > 999)
  throw new rangeerror(`invalid status code: ${statuscode}`);

if (common._checkinvalidheaderchar(this.statusmessage))
  throw new error('invalid character in statusmessage.');

  这里使用了javascript中的按位或运算符:| 。其目的是将所有非数字的statuscode都默认转换成0。可以参考以下两篇文章中的描述来理解javascript中的位运算符:

  

  https://developer.mozilla.org/zh-cn/docs/web/javascript/reference/operators/bitwise_operators#bitwise_xor

  值得注意的是,当参与计算的值不能隐式转换成数字时,得到的结果为0,可以参考上面第二篇文章中给出的一些实际例子。

  在实际应用中,巧妙使用位运算符,可以非常方便地实现我们想要的效果,例如,判断一个给定的数值是否为偶数、找出给定数值最接近的偶数、判断一个字符串是否包含在另一个字符串中等等。