未古其人

目录

记一次恶心到家的错误调查

闲来无事把nodejs 升级到了 v6.10.0,然后遇到了一个非常奇怪的问题。

    TypeError: The header content contains invalid characters
           at storeHeader (_http_outgoing.js:318:11)
           at ServerResponse.OutgoingMessage._storeHeader (_http_outgoing.js:228:9)
           at ServerResponse.writeHead (_http_server.js:221:8)

WTF,这什么鬼?!
开始以为自己哪里写错代码来,但想来之前的版本都没错,应该不是我的问题。于是一边上google搜索,一边去查文档,翻各种论坛记录。

最后,还是在查阅了 nodejs 的源代码之后,才终于让我发现了错误的原因。

_http_outgoing.js 这个文件在 318 行调用了下面这个函数(位于_http_common.js 的 303-326 行 )。

function checkInvalidHeaderChar(val) {
  val += '';  if (val.length < 1)    return false;  var c = val.charCodeAt(0);  if ((c <= 31 && c !== 9) || c > 255 || c === 127)    return true;  if (val.length < 2)    return false;
  c = val.charCodeAt(1);  if ((c <= 31 && c !== 9) || c > 255 || c === 127)    return true;  if (val.length < 3)    return false;
  c = val.charCodeAt(2);  if ((c <= 31 && c !== 9) || c > 255 || c === 127)    return true; /*
  * 就是下面这个 for 循环造成的原因。
  * 在添加非ASCII字符之后,这里会被 判断为非法字符而被 check 出来,
  * 于是就在 _http_outgoing.js 的 318 行抛出 TypeError。  
  */
  for (var i = 3; i < val.length; ++i) {
    c = val.charCodeAt(i);    if ((c <= 31 && c !== 9) || c > 255 || c === 127)      return true;
  }  return false;
}

然后现在我在 cookie 中插入了点中文之后,就华丽丽的浪费了快一个小时。
原因找到了,解决方案也就出来了——虽然比较挫。遇到符合以上标准的字符的时候,就直接转换成UNICODE码。

但是,看到了这段代码,就还是想要问,为什么这里会加上这么一段检查呢?这个问题就留给下次解决吧。
好像StackOverflow 上似乎也有人问过,github上也有人提过类似的 issue,但因为全是英文就没去仔细看了,等着有机会再去看看。