预检(OPTIONS)请求

630 阅读3分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动

在浏览器中通过http请求与服务端进行请求时,偶尔会发现某一些请求会被调用两次,一次是符合我们业务需求的接口调用,一次是在我们预料之外的请求,而且这个请求还不会有任何的数据返回,咋一看似乎是哪里出了问题,这个请求便是预检请求(request method为OPTIONS)

首先看一下MDN对于其定义

HTTP 的 OPTIONS 方法 用于获取目的资源所支持的通信选项。客户端可以对特定的 URL 使用 OPTIONS 方法,也可以对整站(通过将 URL 设置为“*”)使用该方法。

为何会存在OPTIONS请求呢?

可用于检测服务器允许的 http 方法。当发起跨域请求时,由于安全原因,触发一定条件时浏览器会在正式请求之前自动先发起 OPTIONS 请求,即 CORS 预检请求,服务器若接受该跨域请求,浏览器才继续发起正式请求

什么时候会发起OPTIONS请求呢?

一个 CORS 预检请求是用于检查服务器是否支持 CORS 即跨域资源共享,当有必要的时候,浏览器会自动发出一个预检请求;所以在正常情况下,我们不需要自己去发这样的请求

在跨域的情况下:

当发送的请求为非简单请求时,这个时候浏览器会自动的帮我们发送一个OPTIONS请求,用于检测所请求的目标资源是否支持跨域,当浏览器发送OPTIONS请求得到响应之后,会根据responst header自动处理,若是目标资源支持跨域则会继续将正常的请求发送,若是不支持跨域则直接控制台报错,提示当前请求跨域了

若是发送的请求为简单请求时,则不会发送OPTIONS请求,浏览器会直接将请求正常发送

什么是简单请求、复杂请求?

当只包含简单头部时,一个请求则被视为简单请求并且在跨域中不需要发送OPTIONS请求,那么什么样的请求是简单请求呢?

请求方法(Request Method)为 GET、POST、HEAD之一时

HTTP header修改了如下的值,依旧是简单请求:

Accept: 请求头用来告知(服务器)客户端可以处理的内容类型

Accept-Language:请求头允许客户端声明它可以理解的自然语言,以及优先选择的区域方言

Content-Language: 是一个 entity header(实体消息首部),用来说明访问者希望采用的语言或语言组合,这样的话用户就可以根据自己偏好的语言来定制不同的内容

Content-Type: 实体头部用于指示资源的MIME类型, 值是 application/x-www-form-urlencoded, multipart/form-data, 或者 text/plain之一的(忽略参数)

或者以下客户端头部之一的也可以被认为是简单头部:

DPR: 请求头是“客户端提示” (en-US)消息头,它代表客户端设备的像素比(DPR),该比例是与每个CSS像素相对应的物理设备像素的数量。

Downlink: 下行网络客户端提示请求头字段提供了近似带宽的客户端连接到服务器

Save-Data: 请求头字段是一个布尔值,在请求中,表示客户端对减少数据使用量的偏好。 这可能是传输成本高,连接速度慢等原因。

Viewport-Width: 设备客户端提示请求头提供了客户端CSS布局视口宽度的像素。值是围捕后最小的整数(即上限值)。

符合上述三个条件的都属于简单请求,除此之外的都属于复杂请求