由“RangeError: Invalid status code: 0”錯誤所引發的思考


  最近發現一個基於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進入調試模式,果然復現了本文開頭給出的那個錯誤。

  那么問題來了,為什么給定的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中的位運算符:

  http://www.w3school.com.cn/js/pro_js_operators_bitwise.asp

  https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Bitwise_XOR

  值得注意的是,當參與計算的值不能隱式轉換成數字時,得到的結果為0,可以參考上面第二篇文章中給出的一些實際例子。

  在實際應用中,巧妙使用位運算符,可以非常方便地實現我們想要的效果,例如,判斷一個給定的數值是否為偶數、找出給定數值最接近的偶數、判斷一個字符串是否包含在另一個字符串中等等。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM