有必要显式地设置content-length吗?
发布于 5 年前 作者 LurenAA 4558 次浏览 来自 问答

我之前写代码从来没有设置过content-length,最近看koa-send这个包,在index.js 130行的地方有这样一行代码 ctx.set(‘Content-Length’, stats.size) 但是我把这行取消后用postman请求,发现没有差别,代码也能跑,读到地content-length。 现在问问各位大佬,是否有必要显式地设置content-length吗?

9 回复

不写content-length 客户端怎么读数据呢?

@yakczh 谢谢您的解答,,, 我看到《Http权威指南》p131下面写到,响应实体应该有content-type,content-length 但是在学习node时,很多时候我们写的服务器并没有满足这两个条件 比如菜鸟教程上的这个例子: image.png image.png 可以看到并没有content-length,但是依然可以运行。 到底是content-length是看情况设置,还是这些例程有问题?麻烦您解惑。。

@LurenAA 这是chunked 模式,即分段设长度, post-man显示的数据不是原始数据,是读取以后处理过的 你要自己用net做客户端读一下看看返回的数据,不论是 chunked和content-length 都要设置长度,没有长度,客户端是不知道该读多少字节的

@yakczh 你说的是对的,但可能会让楼主产生一些误解。

其实chunked模式也是设置了长度,但长度隐藏在内容的报文中,楼主你用的工具看不到。

而chunked的实现如下:

// 直接使用socket简单实现http1.1协议chunked部分
const net = require('net');
const port = 3000;
net.createServer((socket) => {
    socket.on('data',(data)=>{
        let msg = data.toString();
        console.log(msg) //读取的客户端请求数据
        socket.write('HTTP/1.1 200 OK\r\n');
        socket.write(`Date: ${new Date().toGMTString()}T\r\n`);
        socket.write('Content-Type: text/html\r\n');
        socket.write(`Transfer-Encoding: chunked\r\n`);
        socket.write(`\r\n${(12).toString(16)}\r\n`);// 这里是16进制数字,表示后面有12字节数据
        socket.write('Hello World!');
        socket.write(`\r\n0\r\n\r\n`); // say Bye-Bye
    });
}).listen(port);
console.log(`use: curl -v http://127.0.0.1:${port}`)

在这里面你可以看到,这里就是声明了chunk的字节长度

 socket.write(`\r\n${(12).toString(16)}\r\n`);

同时最后say Bye-Bye的时候,声明了后续的长度为0,最后已回车确认结束

那么content-length和chunked有什么区别呢? 即是声明了content-length需要将内容报文一次给出,而chunked不用。

比如我修改一下代码:

// 直接使用socket简单实现http1.1协议chunked部分
const net = require('net');
const port = 3000;
net.createServer((socket) => {
   socket.on('data',(data)=>{
       let msg = data.toString();
       console.log(msg) //读取的客户端请求数据
       socket.write('HTTP/1.1 200 OK\r\n');
       socket.write(`Date: ${new Date().toGMTString()}T\r\n`);
       socket.write('Content-Type: text/html\r\n');
       socket.write(`Transfer-Encoding: chunked\r\n`);
       socket.write(`\r\n${(12).toString(16)}\r\n`);// 这里是16进制数字,表示后面有12字节数据
       socket.write('Hello World!');
       socket.write(`\r\n${(4).toString(16)}\r\n`);  // ### 注意这是新增的部分 ###
       socket.write('Boy!'); // ### 注意这是新增的部分 ###
       socket.write(`\r\n0\r\n\r\n`); // say Bye-Bye
   });

}).listen(port);
console.log(`use: curl -v http://127.0.0.1:${port}`)

注意我新增的部分。chunked可以利用不断的追加内容。在尾部增加报文的长度,实现段传输,最后完成后合成一个完整的http。content-length在开始就定义好了长度,所以content-length不能像chunked一样,一直在尾部增加长度和内容。 因为chunked是在http1.1增加的,必须的说法可能是你这本书可能有点年纪了。

@LurenAA 我觉得你的提问很好,我能用你的截图写一份博客记录一下么?如果不能,我这边就撤回使用的素材了,谢谢。

@zy445566 可以,谢谢您的解答

@zy445566 学习了,牛逼啊

@hyj1991 谢谢大佬捧场

回到顶部