Node Express Content-Length

33

我在一个小项目中使用了node.js和express。我设置响应头如下:

res.set({'Content-Type':'text/plain;charset=utf-8',    
'Content-Length': Buffer.byteLength(data, 'utf-8')});       

我可以使用 console.log 打印数据长度为317。但是在浏览器控制台中,我只能看到以下内容:

Connection:keep-alive
Content-Encoding:gzip
Content-Type:text/plain;charset=utf-8
Date:Sat, 01 Jun 2013 08:21:59 GMT
Transfer-Encoding:chunked
Vary:Accept-Encoding
X-Powered-By:Express

那么,为什么content-length消失了呢?

1个回答

55
响应中有Transfer-Encoding: chunked。这里不适用Content-Length,因为内容以一个或多个部分(块)的形式在响应体内发送,并使用标记指示每个单独块的字节长度。 http://en.wikipedia.org/wiki/Chunked_transfer_encoding Node.js默认使用Transfer-Encoding: chunked。但是,通过在本机http响应对象上设置Content-Length头来禁用它。 HTTP模块文档说:

发送“Content-length”头将禁用默认的块编码。

根据响应中的Content-Encoding:gzip头,您可能已启用connect.compress中间件。 connect.compress中间件会删除Content-Length头。
无论如何,除非您自己生成gzipped内容,否则您自己生成的Content-Length头部肯定不适用于最终(gzipped)响应正文。幸运的是,连接中间件会为您处理这个问题。
在使用Express或Connect时,您不应假设使用res对象发送的内容实际上以该方式发送到客户端。中间件处于其中。所有中间件都可以更改响应的几乎任何内容,包括更改响应正文,添加,删除和更改标头。请求也是如此。
另请参阅以下问题:

3
抱歉,我不知道是谁给我点了这个踩,但你是对的。非常感谢你。在添加 app.use(express.compress()); 后,content-length 显示出来了。但是,我可以同时使用 gzip 和 content-length 吗? - Allen Heavey
@DMDGeeker,原则上,您可以同时使用“Transfer-Encoding: gzip”和“Content-Length”。但是,不能与“express.compress”中间件一起使用。它不支持这个。原则上,如果您可以知道响应长度,则最好发送Content-Length头。您可以自己压缩内容或寻找不同的“压缩”中间件。但是,“Content-Length”必须反映实际发送的内容。它必须反映最终(可能已压缩)正文的字节长度。 - Myrne Stol
connect.compress 不会在响应中添加新的 Content-Length 的原因是它需要缓冲压缩后的响应体。只有当缓冲区完整时,才能知道内容长度。 - Myrne Stol
如果您使用 zlib.gzip 自己压缩缓冲区,然后执行 res.set({"Transfer-Encoding": "gzip"}),那么 connect.compress 中间件将不会处理它。 - Myrne Stol
谢谢。我会尝试的。 - Allen Heavey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接