在写live-dev-server,向html文件中inject代码片段时,设定Content-Length出现了ERR_CONTENT_LENGTH_MISMATCH。

Content-Length

developer.mozilla.org/en-US/docs/…

Content-Length实体标头指示发送给接收者的实体主体的大小(以字节为单位)。用十进制标识的8位字节。

当浏览器接收内容的时候,如果设定了比正确的内容长度小的Content-Length,浏览器接收到内容就会被截断。如下,body,html标签已经被截断了:Content-Length的计算_Content-Length

如果设定大了,浏览器就会一直处于等待加载更多内容的状态,然后再抛出ERR_CONTENT_LENGTH_MISMATCH。Content-Length的计算_Content-Length_02

res.setHeader('Content-Length', len + 200)复制代码

英文、数字长度计算

服务端在设定Content-Length的时候,可以设置charset,一般设定为UTF-8。我们在计算长度的时候,UTF-8编码下,英文、数字用一字节编码。如下伪代码:

const INJECT_STR = fs.readFileSync('./inject', { encoding: 'utf-8' })// 在返回的时候let len = INJECT_STR.length
len += res.getHeader('Content-Length')
res.setHeader('Content-Length', len)复制代码

这个一般是没有问题的,但是前提是在inject文件里,没有出现中文。如果出现中文,就会有截断的情况出现。

中文长度计算

UTF-8里面,绝大多数中文是3个字节,字符串的length是1,这就造成了结果长度必然小于实际长度,导致内容被截断。 计算的方式可以用下面的方法计算,

参考见 stackoverflow.com/questions/5…

1. Blob size

var str = '中国'new Blob([str]).size // 6复制代码

2. charCodeAt

stackoverflow.com/questions/5…

function byteLength(str) {  // returns the byte length of an UTF-8 string
  var s = str.length;  for (var i=str.length-1; i>=0; i--) {var code = str.charCodeAt(i);if (code > 0x7f && code <= 0x7ff) s++;else if (code > 0x7ff && code <= 0xffff) s+=2;if (code >= 0xDC00 && code <= 0xDFFF) i--; //trail surrogate
  }  return s;
}
byteLength(str) // 6复制代码

3. Buffer.byteLength

# node> var str = '中国'undefined
> Buffer.byteLength(str, 'utf8')
6复制代码

总结

  1. 在如果中文可以不要的情况下,尽量改用英文。
  2. 使用方法正确计算出Content-Length。
  3. node中使用Buffer.byteLength或Blob计算长度。