Node.js没有对HTTP响应标头使用ISO-8859-1编码

Node.js not using ISO-8859-1 encoding for HTTP response headers

本文关键字:ISO-8859-1 编码 响应 js HTTP Node      更新时间:2023-09-26

我有一个HTTP响应标头,其中包含ISO-8859-1字符(é0x39)。下面是显示HTTP响应的原始数据包捕获,底部第二行:

00000000  48 54 54 50 2f 31 2e 30  20 32 30 30 20 4f 4b 0d HTTP/1.0  200 OK.
00000010  0a 43 6f 6e 74 65 6e 74  2d 54 79 70 65 3a 20 61 .Content -Type: a
00000020  75 64 69 6f 2f 61 61 63  70 0d 0a 69 63 79 2d 62 udio/aac p..icy-b
00000030  72 3a 34 30 0d 0a 69 63  79 2d 67 65 6e 72 65 3a r:40..ic y-genre:
00000040  4a 61 7a 7a 20 4c 6f 75  6e 67 65 20 43 61 66 65 Jazz Lou nge Cafe
00000050  0d 0a 69 63 79 2d 6e 61  6d 65 3a 43 61 66 e9 20 ..icy-na me:Caf. 
00000060  64 65 20 50 61 72 69 73  20 2d 20 52 41 44 49 4f de Paris  - RADIO

标题应为:

icy-name:Café de Paris

我提出了一个非常简单的http.get()请求:

http.get('http://example.com/streamUrl', function (res) {
    console.log(res.headers);
});

在我的控制台上,我看到:

'icy-name': 'Caf� de Paris',

然后我尝试将字符串转换为缓冲区:

console.log(new Buffer(res.headers['icy-name']));
// <Buffer 43 61 66 ef bf bd 20 64 65 20 50 61 72 69 73 ... >

在转换到我的缓冲区之前,或者在转换过程中,原始字符0xe9似乎已经丢失。然后,我想也许iconv-lite会有所帮助:

var iconv = require('iconv-lite');
iconv.extendNodeEncodings();
console.log( (new Buffer(res.headers['icy-name'], 'latin1')).toString('utf8') );
// "Caf? de Paris" with a literal question mark, `0x3F`.

我怀疑在我的代码获得响应标头值之前,已经造成了损坏。我的问题:

  1. Node.js的HTTP客户端首先错误地解释了字符串,我的假设正确吗
  2. 是否有配置Node.js以正确处理HTTP响应的方法?RFC5987说HTTP响应的默认字符集是ISO-8859-1
  3. 如果没有办法让Node.js正常工作,有没有办法撤消转换损坏,恢复原始的ISO-88591-1字符串,然后转换为UTF-8

不幸的是,据我所知,没有一个官方规范被广泛用于在HTTP标头中传输非ACSII数据。您链接到的RFC仅处于PROPOSED STANDARD状态,并且是从2010年开始的。看起来Node 0.10显式地将头值传递给了基本上new String(val),因此这些值被解析为utf8值。看起来在节点0.11中,字符串没有那么混乱,所以

var iconv = new Iconv('ISO-8859-1', 'UTF-8');
console.log(iconv.convert(new Buffer(res.headers['icy-name'], 'binary')));

确实如您在0.11中所期望的那样工作。我不能确定这是故意的,还是只是其他工作的副作用。

FWIW我刚刚写了一个Http.Agent,它将解码从latin1到utf8的标头数据,并覆盖原始标头。