目录
一、http协议基础
概念
HTTP协议(HyperText Transfer Protocol
,超文本传输协议)是用于从WWW服务器传输超文本到本地浏览器的传输协议。
当你在浏览器的地址框中输入一个URL(www.baidu.com)或是单击一个超级链接时,URL就确定了要浏览的地址。浏览器通过超文本传输协议(HTTP),将Web服务器上站点的网页代码提取出来,并翻译成漂亮的网页。
我们需要获取到服务器上的资源或者请求服务器的接口,都要发送请求(不一定必须是http请求)。
请求报文(Request)
客户端发送一个HTTP请求到服务器的请求消息包括以下格式:请求行(request line)、请求头部(header)、空行和请求数据四个部分组成。
GET /hello.txt HTTP/1.1
User-Agent: curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
Host: www.example.com
Accept-Language: en, mi
常用请求方法:
响应报文(Response)
HTTP响应也由四个部分组成,分别是:状态行、消息报头、空行和响应正文。
二、http缓存
在浏览器加载资源的时候,首先会根据请求头的expires和cache-control判断是否命中强缓存策略,判断是否向远程服务器请求资源还是去本地获取缓存资源。
http强缓存
在浏览器中,强缓存分为Expires(http1.0规范)、cache-control(http1.1规范)两种。
Expires
Expires是http1.0的规范,用于表示资源的过期时间的请求头字段,值是一个绝对时间
(到期时间),是由服务器端返回的。
在浏览器第一个请求资源时,服务器端的响应头会附上Expires这个响应字段,当浏览器在下一次请求这个资源时会根据上次的expires字段是否使用缓存资源(当请求时间小于服务端返回的到期时间
,直接使用缓存数据)
注意:
expires是根据本地时间来判断的,假设客户端和服务器时间不同,会导致缓存命中误差
cache-control
Expires有个缺点,当客户端本地时间和服务器时间不一致时会产生误差
,浏览器会直接向服务器请求新的资源,为了解决这个问题,在http1.1规范中,提出了cache-control
字段,且这个字段优先级高于
上面提到的Expires,值是相对时间
。
cache-control中有常见的几个响应属性值:
例如下面是一张图片的响应:
http协商缓存
强缓存都是由本地浏览器
确定是否使用缓存,当浏览器没有命中强缓存时就会向浏览器发送请求,验证协商缓存
是否命中,如果缓存命中则返回304
状态码,否则返回新的资源数据。
同样,协商缓存的标识也是在响应报文的HTTP头和请求结果一起返回给浏览器的,控制协商缓存的字段分别有:
- Last-Modified / If-Modified-Since
- Etag / If-None-Match
其中Etag/If-None-Match优先级
比Last-Modified/If-Modified-Since高。
Last-Modified / If-Modified-Since
Last-Modified
是服务器响应请求时,返回该资源文件在服务器最后被修改的时间
。
If-Modified-Since则是客户端再次发起该请求
时,携带上次请求返回的Last-Modified值,通过此字段告诉服务器该资源上次请求返回的最后被修改时间。服务器收到该请求,发现请求头含有If-Modified-Since字段,则会根据If-Modified-Since的字段值与该资源在服务器的最后被修改时间做对比
:
- 若服务器的资源最后修改时间大于If-Modified-Since的字段值,则重新返回资源,状态码为200;
- 否则返回304,代表资源无更新,可以继续使用缓存文件。
Etag / If-None-Match
Etag是服务器响应请求时,返回当前资源文件的一个唯一标识
(由服务器生成)。
If-None-Match是客户端再次发起请求时,携带上次
请求返回的唯一标识Etag值,服务端收到该请求后,发现该请求含有If-None-Match,则会根据If-None-Match的字段值与该资源在服务器的Etag值做对比:
- 一致则返回304,代表资源无更新,继续使用缓存文件。
- 否则重新返回资源,状态码为200。
所以协商缓存结果:
- 协商缓存生效,返回304,服务器告诉浏览器资源未更新,则直接浏览器缓存中访问资源。
- 协商缓存失效,返回200和请求结果,这个结果是从服务器返回的新的结果。
缓存流程
了解了强缓存和协商缓存,那么我们可以大概描述一下一次完整的请求流程:
- 当浏览器发起一个资源请求时(例如一张图片),浏览器会先判断本地是否有缓存记录,如果没有会向浏览器请求新的资源,并记录服务器返回的last-modified。
- 如果有缓存记录,先判断
强缓存
是否存在(cache-control优先于expires),如果强缓存的时间没有过期则返回本地缓存资源
(状态码为200
)。 - 如果强缓存失效了,客户端会发起请求进行
协商缓存策略
,首先服务器判断Etag
标识符,如果客户端传来标识符和当前服务器上的标识符是一致的,则返回状态码 304 not modified(不会返回资源内容)。 - 如果没有Etag字段,服务器会对比客户端传过来的
if-modified-match
和服务器上资源的最后修改时间,如果这两个值是一致的,此时响应头不会带有last-modified字段(因为资源没有变化,last-modified的值也不会有变化),客户端304状态码之后读取本地缓存。如果If-Modified-Since的字段值与该资源在服务器的最后被修改时间不一样,那么返回新资源,状态码为200。 - 如果Etag和服务器端上的不一致,重新获取新的资源。
简化:
强缓存->(cache-control > expires) [强缓存失败] -> 协商缓存 -> (Etag > last-modified) -> [协商缓存失败] -> 重新获取资源