天天看点

测试提了个bug,为什么你多了个options请求?

作者:农民工说前端

序言

测试给我提了个bug,说为什么一次操作,network里面两个请求。

我第一反应是。。。

测试提了个bug,为什么你多了个options请求?

走过去一瞧,原来是多了个options请求。

“这个你不用管,这个是浏览器默认发送的一个预检请求”。可是测试很执着:“这可肯定不行啊,明明是一次请求,为什么要两次呢?“。

“挺固执啊,那我就给你讲个明白”。

概述

当一个资源从与该资源本身所在的服务器不同的域、协议、端口请求一个资源时,资源会发起一个跨域 HTTP 请求。

出于安全原因,浏览器限制从脚本内发起的跨源HTTP请求,只能从加载应用程序的同一个域请求HTTP资源,除非使用CORS头文件。

对于浏览器限制这个词,要着重解释一下:不是浏览器限制了发起跨站请求,是跨站请求可以正常发起,但是返回结果被浏览器拦截了。

CORS概述

跨源资源共享标准新增了一组 HTTP 标头字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源。

另外,规范要求,对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求),浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨源请求。

服务器确认允许之后,才发起实际的 HTTP 请求。在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(例如 Cookie 和 HTTP 认证相关数据)。

测试提了个bug,为什么你多了个options请求?

简单请求

不会触发CORS预检的请求称为简单请求,满足以下所有条件的才会被视为简单请求。

  1. 使用其中一种方法
  2. 只使用了如下的安全首部字段,不得人为设置其他首部字段
  • AcceptAccept-Language
  • Content-Language
  • Content-Type 仅限以下三种text/plain、multipart/form-data、application/x-www-form-urlencoded

预检请求

需预检的请求要求必须首先使用 OPTIONS 方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求。"预检请求“的使用,可以避免跨域请求对服务器的用户数据产生未预期的影响。

下面的请求会触发预检请求,其实非简单请求之外的就会触发预检,就不用记那么多了。

  1. 使用了方法
  2. 人为设置了非规定内的其他首部字段,参考上面简单请求的安全字段集合,还要特别注意Content-Type的类型。

以下是一个发起预检请求的例子

发起请求的origin与请求的服务器的host不同,而且根据上面的条件判断,触发了预检

测试提了个bug,为什么你多了个options请求?
测试提了个bug,为什么你多了个options请求?

请求附带身份凭证 -> cookies

如果发起请求时设置withCredentials 标志设置为 true,从而向服务器发送cookie, 但是如果服务器端的响应中未携带Access-Control-Allow-Credentials: true,浏览器将不会把响应内容返回给请求的发送者。

完整请求流程

测试提了个bug,为什么你多了个options请求?

点关注,不迷路。

做干净纯粹的技术分享,有话评论区走起来。