提前致谢。
由于请求中的Accept
标头,Express JS 4.0会更改输出数据。
有没有办法让我覆盖这种行为,只需编写相同的数据,无论请求标头如何。
当Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
存在时,输出会发生变化。
有没有办法可以忽略,删除,覆盖这些标题。
我正在尝试从Node / ExpressJS应用程序提供二进制数据。 我正在存储一个压缩的日志文件(纯文本/文本),它已被gzip压缩,base64编码并发送到我的服务器应用程序,在那里它使用mongoose存储在mongo数据库中。我知道这可能不是最佳,但目前是一个必要的邪恶。这很好。
$(gzip --stdout /var/log/cloud-init-script.log | base64 --wrap=0)
在将数据作为json帖子的一部分与其他数据一起发送之前,用于压缩和base64数据。
当我尝试检索,解码base64编码的字符串并以二进制gzip文件的形式发送到浏览器时,会出现问题。
// node, referring to the machine the log came from
var log = new Buffer(node.log, 'base64');
res.setHeader('Content-Disposition', 'attachment; filename=' + node.name + "-log.gz");
res.setHeader('Content-Type', 'application/x-gzip');
res.setHeader('Content-Length', log.length);
console.log(log.toString('hex'));
// res.end(log, 'binary'); I tried this hoping I could by pass, some content-negotiation
res.send(log);
使用res.send
使用ExpressJS 3.0时,我的工作正常。
但是当我更新到ExpressJS 4.0时,下载的数据不再正常提取。被扯下来的数据似乎在某种程度上被腐蚀了。
我开始尝试通过使用xxd
或od
比较下载文件和十六进制输出中的源文件来解决此问题,并发现下载的文件与源不同。在将NodeJS缓冲区发送到客户端到控制台之前,我也将其转储,这与源匹配。
我一直在猛烈抨击这一发布近一天,并且怀疑NodeJS可能正在做一些时髦的字符编码(UTF-8 v.Buffer v.UTF16 Strings),OS endianess。
最终发现这一切都不是问题,我原以为NodeJS一直在向浏览器输出错误的数据,这是正确的,但它不是"总是"输出错误的数据。
我有一个突破,当我向端点发出curl请求,并且数据按预期传出(与源匹配)时,我添加了随浏览器请求发送的请求标头,然后返回错误的数据。
实际日志文件:
I'm a log file
> User-Agent: curl/7.37.1
> Host: 127.0.0.1:9000
> Accept: */*
>
< HTTP/1.1 200 OK
< X-Powered-By: Express
< Last-Modified: Tue, 26 May 2015 11:47:46 GMT
< Content-Description: File Transfer
< Content-Disposition: attachment; filename=test-log.gz
< Content-Type: application/x-gzip
< Content-Transfer-Encoding: binary
< Content-Length: 57
< Date: Tue, 26 May 2015 11:47:46 GMT
< Connection: keep-alive
0000000: 1f8b 0808 0256 6455 0003 636c 6f75 642d .....VdU..cloud-
0000010: 696e 6974 2d73 6372 6970 742e 6c6f 6700 init-script.log.
0000020: f354 cf55 4854 c8c9 4f57 48cb cc49 e502 .T.UHT..OWH..I..
0000030: 003b 5ff5 5f0f 0000 00 .;_._....
> Host: localhost:9000
> Connection: keep-alive
> Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
> User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.65 Safari/537.36
> Referer: http://localhost:9000/nodes?query=environment%3D5549b6cbdc023b5e26fe6bd4%20type%3Dnat
> Accept-Language: en-US,en;q=0.8
>
< HTTP/1.1 200 OK
< X-Powered-By: Express
< Last-Modified: Tue, 26 May 2015 11:47:00 GMT
< Content-Description: File Transfer
< Content-Disposition: attachment; filename=test-log.gz
< Content-Type: application/x-gzip
< Content-Transfer-Encoding: binary
< content-length: 57
< Date: Tue, 26 May 2015 11:47:00 GMT
< Connection: keep-alive
0000000: 1ffd 0808 0256 6455 0003 636c 6f75 642d .....VdU..cloud-
0000010: 696e 6974 2d73 6372 6970 742e 6c6f 6700 init-script.log.
0000020: fd54 fd55 4854 fdfd 4f57 48fd fd49 fd02 .T.UHT..OWH..I..
0000030: 003b 5ffd 5f0f 0000 00 .;_._....
答案 0 :(得分:1)
res.end(node.log, 'base64');
而不是
res.send(log);
其中node.log是原始base64编码的String,而log是已解码该字符串的Buffer。
请记住我使用的是Node v0.10.38。
我最终关注了函数调用链。
// I call
res.send(log);
// ExpressJS calls on http.ServerResponse
this.end(chunk, encoding); // chunk = Buffer, encoding = undefined
// NodeJS http.ServerResponse calls
res.inject(string);
此时NodeJS似乎将数据视为字符串,这是缓冲区内容被破坏的地方。
当'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
标头不存在时,此行为不同,在这种情况下调用了不同的end(chunk, encoding)
函数,而不是使用res.inject
而不是修改缓冲区数据。
我不完全确定内容协商的发生位置以及在不同res.end
函数中交换的内容,无论是NodeJS还是ExpressJS,但能够在某些内容协商中控制此内容协商会很好简单的方法。