http比较常用的消息头如下所示:
General #概要
Request URL: http://127.0.0.1:3001/index.html #请求地址
Request Method: GET #请求方式
Status Code: 304 Not Modified #状态码,304返回空响应体
Remote Address: 127.0.0.1:3001 #服务器地址
Response Headers #应答头部
Connect: keep-alive #长连接,比如要请求一个页面上的十张图,只需要建立一次tcp连接,然后依次请求十张图,等待资源响应,释放连接。
Content-Length: 100 #内容的传输长度
Content-Type: text/html #内容类型
Cache-Control: max-age=3600 #缓存声明,也可以在请求头使用
ETag: "ab10633a" #资源指纹信息,用于缓存校验
Last-Modified:Thu,20 Sep 2019 15:10:10 GMT #资源最后修改时间,用于缓存校验
Transfer-Encoding: chunked #分块传输
Content-Encoding: gzip #压缩
Request Headers #请求头部
Accept: text/html #浏览器希望接收的数据类型
Accept-Encoding:gzip,deflate #浏览器希望接收的编码
If-Modified-Since:Thu,20 Sep 2019 15:10:10 GMT #发送的是资源最后的修改时间,跟服务器的修改时间比较
Cache-Control:no-cache #缓存声明,也可用在响应头
If-None-Match:"ab10633a"#将上次的Etag发出去,做缓存校验
其中比较重要的是缓存消息头和传输消息头,我们下面来重点剖析一下。
Cache-Control
首先说缓存消息头,主要是Cache-Control。
Cache-Control的常用取值是:no-store、max-age、no-cache。
Cache-Control: no-store #所有内容都不会被保存到缓存。
Cache-Control: no-cache #代理服务器不用缓存,要向源服务器发起请求
Cache-Control:max-age=3600 #最大缓存时间是3600秒
还记得nginx这个配置吧:
location ~ .*\.(?:js|css)$ {
expires 1h;
}
其实这个配置等同于Cache-Control:max-age=3600,同时会在响应头看到Etag字段。
Etag
Etag,就是Entity tag,它代表资源的指纹信息。用于缓存校验。什么是缓存校验呢?
比如你请求服务器的一个资源,如果这个资源更新了,也就是Etag指纹信息发生了变化,那浏览器通过比较Etag就知道要刷新缓存;又或者是浏览器缓存的资源过期了,但服务器的资源仍是旧的,此时也不需要重新发送。
如何比较Etag指纹信息呢?过程是这样的:
当浏览器第一次请求一个服务器资源,响应头会带上Etag字段;然后浏览器再次请求这个资源,那请求头就会带上If-None-Match这个字段,它的值就是Etag的值。它的意思就是说,如果浏览器和服务端的Etag都是一致的,也就是资源还是旧的,那就返回304(304代表浏览器会调用缓存资源),如果不一致,则返回200和新的资源,并带上Etag字段(响应头)。
那如何知道资源是否过期了呢?
当浏览器第一次请求一个服务器资源,响应头会带上Last-Modified字段;然后浏览器再次请求这个资源,请求头就会带上If-Modified-Since,这个字段的值就是Last-Modified的值,服务端接收到后会检查该时间是否与服务器的最后修改时间相一致,如果一致,仍返回304,如果不一致,返回200和最新的资源,并带上Last-Modified字段(响应头)。

gzip
在http协议中,可以对body内容部分进行压缩传输,这样会节省带宽,提高用户显示网页的速度。
那么具体的压缩过程是怎样的呢?
第1步:
浏览器发送一个请求头request,带上Accept-Encoding:gzip,deflate,这个就是告诉服务器:浏览器支持gzip压缩;
第2步:
服务器接收到request后,生成原始response,里面有Content-Type和Content-Length字段;
第3步:
服务器通过gzip对原始response进行编码压缩,编码后的header头就增加了Content-Encoding:gzip,然后把压缩过的response发送给浏览器;
第4步:
浏览器接到response后,根据Content-Encoding:gzip,对response进行解码,获取到原始response内容后,显示出网页。
那什么时候响应头会带上Transfer-Encoding: chunked呢?这个字段代表什么?
我们再往深处发掘。
在第3步,如果是一个很大的response(比如视频),在将原始response进行gzip压缩时,服务器会在内存申请一个很大的数组,将整个压缩后的数据暂存在里面,这样数组的大小就是Content-Length了。那么这种做法很显然是浪费资源的,我们可以分成小块传输,这样就不用占用大块的内存资源了,响应头带上Transfer-Encoding: chunked,就是告诉浏览器端这是分块传输的资源,因为http1.1有长连接keep-alive,因此分块传输是可行的。

网友评论