我与浏览器请求的那些记录

776 阅读7分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情

为什么要写这篇文章

一直以来对http这块都比较陌生,在日常的前后端开发中,也只知道200,404,500这些日常出现的情况,偶尔出现一些特殊情况或者红色意外,也为了赶业务没有过多的追究,本文就对个人在前端工作中遇到http相关的一些情况进行一个总结以及梳理

CORS error

image.png 这就是跨域!!!

  • 提出疑问:为什么会有跨域这个东西? 因为浏览器有一个叫做同源策略的东西,你现在的行为触发了这个东西。
  • 什么是同源策略? 同源策略就是限制不同的源之间的交互的安全策略。 同源: 同协议,同域名,同端口三个都相同。 当触发到这个策略的时候,就会发生跨域的Error。
  • 同源策略有什么用? 很喜欢知乎上看到的一个比喻: 我们家的房子就是一个源,在没有经过我的同意下,不允许陌生人进入,如果随便由陌生人进入了,那么我们家就不安全了,陌生人做什么我们都不知道了。 同源策略就是那个门和锁。 有了这个同源策略就可以有效阻止本源外的一些恶意行为。
  • 那总有情况需要:A源访问B源的数据,怎么给同源策略开个后门?
    后端的小伙伴(可能是你本人,哈哈哈)在B源中设置响应头 Access-Control-Allow-Origin
"Access-Control-Allow-Origin":"*" //允许所有源都可以访问
"Access-Control-Allow-Origin": "http://127.0.0.1:8888" // 只允许 http://127.0.0.1:8888 源可以访问

👌 通过通过,成功获取数据

一个接口请求了两次???

image.png 可以看到上图中一个请求发了两次(确保代码只调了一次噢),为什么呢 因为一次是预请求,一次是正常的请求。

  • 啊,什么是预请求😥
    因为在跨域请求中,分为了两种请求,一种叫简单请求 和 非简单请求
    非简单请求下,就会发出预请求
    浏览器区分简单请求:

    1. 请求方法是以下三种方法之一:HEAD GET POST
    2. HTTP的头信息不超出以下几种字段:Accept Accept-Language Content-Language Last-Event-ID Content-Type:只限于三个值 application/x-www-form-urlencodedmultipart/form-datatext/plain 满足以上两个条件的都是简单请求,其他的都是非简单请求
  • 预请求有什么作用?
    在非简单请求下,先向服务器询问,是否能接受这种类型的请求。

  • 只要发起了预请求,非简单请求就可以了?
    不不不,服务端也要做出对应的设置,现在后端框架基本上已经做好了配置,node使用中间件,java使用拦截器,原理都是设置这几个响应头

      Access-Control-Allow-Methods // 设置允许的请求方法 DELETE,PUT等
      Access-Control-Allow-Headers: // 设置允许的请求头 Content-Type 等
      Access-Control-Max-Age: // 设置这个请求多久内不再需要发起预请求(缓存多少秒)
    

304状态码

除去200404500这些状态码之外,304的状态码相信大家也经常看到,那这个状态码到底是个什么东西呢

  • 为什么会返回304状态码?
    先看下mdn的解释
    " HTTP 304 未改变说明无需再次传输请求的内容,也就是说可以使用缓存的内容。 " 用本人通俗的语言来说,304 未改变,我本地已经缓存了这个文件了,然后询问服务端这个文件可以继续用本地的嘛,服务端告诉你暗号,304,304,没有改变,你可以继续用

  • 小问题:服务端怎么判断你能不能继续用这个资源?

回答问题: 服务器发 Last-Modified (资源最后修改时间),客户端收到后下次通过 If-Modified-Since 发给服务端, 服务端进行一个对比,对比最后修改时间是否改变,告诉客户端能否用这个资源。

  • 问题小伙:那那那万一🙄,我文件修改了,但是内容没有任何变化,这样不得重新请求了?这不浪费嘛
    没事,我们放大招:ETag
    先来解释下Etag, 通俗的话,Etag是资源的标识符,资源内容发生变更了就更新ETag标志😁。
    使用方式:和 Last-Modified 一样,客户端第一次请求资源时,服务端带上ETag 的响应头,客户端拿到之后,缓存到浏览器本地,下次再请求该资源时,通过请求头 If-None-Match 把上次带过来的 ETag 回传给服务端,服务端根据 Etag 进行对比,告诉客户端是否继续使用本地的缓存资源。

ETag的优先级比Last-Modified高,存在Etag,就直接校验ETag了,不会去校验Last-Modified

总结:ETag/If-None-MatchLast-Modified/If-Modified-Since 都是判断资源是否更新的方式,是否可以继续使用缓存,我们管这种对缓存的处理方式,有一个很好听的名字,协商缓存

from memory cache 和 from disk cache

image.png 眼睛非常尖锐的我们,可以看到有一个灰灰的字体 memory cachedisk cache

  • memory cachedisk cache 什么东西来的?
    顾名思义,内存缓存和磁盘缓存

  • 这种cache有什么作用?
    直接从内存缓存或者磁盘缓存中获取资源,不需要再向服务器发起请求,嘿嘿,比协商缓存更厉害了一点,都不用向服务器发起请求了(虽然不能这么形容,哈哈哈哈)

  • 直接从缓存中读取资源,这么节省服务器的方式,怎么用上呢?
    上大哥 Cache-control

image.png

对这种可以直接从本地读取缓存的方式,我们有个名字:强缓存


  • cache-control 除了设置 max-age还可以设置什么东西嘛
    那多的是了,告诉你一些常见的吧

    • max-age:设置缓存存的最长时间
    • no-cache:不直接使用缓存,需要进行协商缓存
    • no-store:不使用任何缓存
    • private:只有客户端才可以缓存,代理服务器不可以缓存
    • public:都可以缓存这个资源,无论你是代理服务器,还是客户端都可以
  • from memory cachefrom disk cache又有什么区别呢
    内存缓存更快,但是存的不多
    磁盘缓存更多,但是稍微慢点
    至于 什么时候用哪一种,表示涉及到我的知识盲区了,我后续学到了一定补上,主要是我也要找不到很好的资料查看,各位要是掘友们看到,评论留下言,哈哈哈哈,发文求答案

  • disable Cache 又是什么来的呢,为什么可以做到直接重新发起请求,不用本地缓存了

image.png 直接告诉各位答案: 勾上了这个 disable cache 就设置了所有的请求头上都设置了请求头cache-controlno-cache

  • 咦,请求头怎么可以设置 cache-control 呢? 可以的,不过这个只支持设置 no-cachemax-age:0,其他值是不会生效的,注意请求头设置和响应头是不一样的。
    • 设置max-age:0走协商缓存
    • 设置no-cache表示这次请求,不走任何缓存,忽视是否过期,文件是否更新

这里粗略总结一下前面提到的浏览器的缓存

image.png

最后

最后的最后,笔者很少写文章,希望这篇文章能给大家带来一些收获,当然如果有错误的地方,大家可以在评论中提出,我们一起成长,希望大家每天都能学到新东西,