http常见状态码实例总结
报文结构
报文结构1.报文首部
报文首部由几个字段组成,http 请求报文由方法,URI,http版本,http首部字段等部分组成
报文首部组成
http常见状态码:
204: no content
该状态码表示请求成功,但是返回响应报文中不含主体部分,返回204后浏览器页面内容不发生更新
举个🌰:当请求一个安全性比较高的接口,第一条请求的Method为OPTIONS,第二条请求的Method才是真正的GET或者POST,并且,第一条请求无数据返回,第二条请求才会返回正常的数据。
OPTIONS是一种“预检请求”,浏览器在处理跨域访问的请求时如果判断请求为复杂请求,则会先向服务器发送一条预检请求,根据服务器返回的内容浏览器判断服务器是否允许该请求访问。如果web服务器采用cors的方式支持跨域访问,在处理复杂请求时这个预检请求是不可避免的。
301: 永久重定向
此状态码表明请求资源被分配新的URI,以后使用资源现在所指的URI。也就是说把这次资源对应URI保存为书签,这时按location提示的URI重新保存
当请求的地址末尾没有加/就会出现301状态码
输入末尾不带‘/’的域名地址
302: 临时重定向
该请求的资源已经被分配新的URI,希望用户访问新的URI
303: 永久重定向
请求对应资源存在着另一个url,应使用get方法定向获取请求资源
302和303有着同样的功能,但是303明确表示客户端应当采用get方法获取资源,这是有别于302的地方
304(协商缓存)
首先声明浏览器缓存分为两种:强制缓存和协商缓存
强制缓存: 浏览器在第一次访问服务器之后,在过期时间内不会去重复请求,这个过程的核心就是知道当前时间是否过期
- http1.0版本: 强制缓存通过 Expires 响应头来实现,expires 表示未来资源会过期的时间,也就是说,请求时间超过了设定时间,表示资源缓存时间到期,会发送请求到服务器重新获取资源。如果请求时间在设定expires时间内,浏览器就会直接读取本地缓存数据库信息
- http1.1: 强制缓存通过 Cache-Control 响应头来实现。Cache-Control 拥有多个值:
private:客户端可以缓存
public:客户端和代理服务器均可缓存;
max-age=xxx:缓存的资源将在 xxx 秒后过期;
no-cache:需要使用协商缓存来验证是否过期;
no-store:不可缓存
最常用的字段就是 max-age=xxx ,表示缓存的资源将在 xxx 秒后过期。一般来说,为了兼容,两个版本的强制缓存都会被实现。
强制缓存只有首次请求才会与服务器通信,读取缓存资源时不会发出任何请求,资源的status状态吗为200,http 1.1 版本的实现优先级会高于 http 1.0 版本的实现。
协商缓存:协商缓存和强制缓存的区别在于协商缓存每次都需要与服务器通信,并增加缓存标识。第一次请求服务器时,服务器返回资源后并且返回一个缓存标识,一起存到浏览器缓存数据库。第二次请求资源时,浏览器会首先将标识发送给服务器,服务器判断标识是否匹配,如果不匹配说明资源更新,服务器将新数据和新标识传给浏览器,如果标识匹配,表示资源没更新,返回304,浏览器就从缓存中读取数据
- http1.0版本:第一次请求通过Last-Modified 来设置响应头的缓存标识,并且把最后修改时间作为值填入,然后将资源返回给浏览器,在第二次请求时,浏览器会首先带上 If-Modified-Since 请求头去访问服务器,服务器会将 If-Modified-Since 中携带的时间与资源修改的时间匹配,如果时间不一致,服务器会返回新的资源,并且将 Last-Modified 值更新,作为响应头返回给浏览器。如果时间一致,表示资源没有更新,服务器返回 304 状态码,浏览器拿到响应状态码后从本地缓存数据库中读取缓存资源。
- http1.1版本:服务器通过 Etag 来设置响应头缓存标识。Etag 的值由服务端生成。在第一次请求时,服务器会将资源和 Etag 一并返回给浏览器,浏览器将两者缓存到本地缓存数据库。在第二次请求时,浏览器会将 Etag 信息放到 If-None-Match 请求头去访问服务器,服务器收到请求后,会将服务器中的文件标识与浏览器发来的标识进行对比,如果不相同,服务器返回更新的资源和新的 Etag ,如果相同,服务器返回 304 状态码,浏览器读取缓存
ETag和Last-Modified的作用和用法,他们的区别:
- Etag要优于Last-Modified。Last-Modified的时间单位是秒,如果某个文件在1秒内改变了多次,那么他们的Last-Modified其实并没有体现出来修改,但是Etag每次都会改变确保了精度;
- 在性能上,Etag要逊于Last-Modified,毕竟Last-Modified只需要记录时间,而Etag需要服务器通过算法来计算出一个hash值(ETag的值,默认是对文件的索引节(INode),大小(Size)和最后修改时间(MTime)进行Hash后得到的。)
- 在优先级上,服务器校验优先考虑Etag。
为什么要有Etag
你可能会觉得使用Last-Modified已经足以让浏览器知道本地的缓存副本是否足够新,为什么还需要Etag呢?HTTP1.1中Etag的出现主要是为了解决几个Last-Modified比较难解决的问题:
- 一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新GET;
- 某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说1s内修改了N次),If-Modified-Since能检查到的粒度是s级的,这种修改无法判断(或者说UNIX记录MTIME只能精确到秒);
- 某些服务器不能精确的得到文件的最后修改时间。
两者区别:
协商缓存与强制缓存的区别在于强制缓存不需要访问服务器,返回结果是200,协商缓存需要访问服务器,如果命中缓存的话,返回结果是304。
截取从缓存取数据的静态资源
应用
频繁变动的资源
对于频繁变动的资源,首先需要使用 Cache-Control: no-cache 使浏览器每次都请求服务器,然后配合 ETag 或者 Last-Modified 来验证资源是否有效。这样的做法虽然不能节省请求数量,但是能显著减少响应数据大小。
代码文件
这里特指除了 HTML 外的代码文件,因为 HTML 文件一般不缓存或者缓存时间很短。
一般来说,现在都会使用工具来打包代码,那么我们就可以对文件名进行哈希处理,只有当代码修改后才会生成新的文件名。基于此,我们就可以给代码文件设置缓存有效期一年 Cache-Control: max-age=31536000,这样只有当 HTML 文件中引入的文件名发生了改变才会去下载最新的代码文件,否则就一直使用缓存。