我之前写代码从来没有设置过content-length,最近看koa-send这个包,在index.js 130行的地方有这样一行代码 ctx.set(‘Content-Length’, stats.size) 但是我把这行取消后用postman请求,发现没有差别,代码也能跑,读到地content-length。 现在问问各位大佬,是否有必要显式地设置content-length吗?
不写content-length 客户端怎么读数据呢?
@yakczh 谢谢您的解答,,, 我看到《Http权威指南》p131下面写到,响应实体应该有content-type,content-length 但是在学习node时,很多时候我们写的服务器并没有满足这两个条件 比如菜鸟教程上的这个例子: 可以看到并没有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 谢谢大佬捧场