这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战
问题
上一篇文章讲了解决跨域请求的几种方式,第一种方式是cors
,趁热打铁,今天顺便来学习下cors下的预检请求,学习这个概念对我们排查网络请求的时候会有帮助。
概念
cors,把请求分为2种
- 简单请求(simple request)
- 非简单请求 (preflight request),请求方法是
OPTIONS
那区分二者的标准是什么? 如下:
- 请求的方法只能是
GET
,POST
,HEAD
的一种 - 请求的header的只能是
Accept
,Accept-Language
,Content-Language
,Content-Type
这些字段,不能超出这些字段 - 对于请求的header的
Content-Type
字段,只能是以下值text/plain
multipart/form-data
application/x-www-form-urlencoded
都满足以上条件的就是简单请求,否则就是非简单请求。
比如我们经常使用的Content-Type:application/json; charset=utf-8
,这个请求就是非简单请求
流程
如果是简单请求,则浏览器会直接
向目标服务器发出请求,如果请求符合cors的配置,则返回结果。
但是如果不是简单请求,浏览器会在发出真正请求前,先发出预检请求
,检查当前请求是否符合服务器的cors配置,如果符合,则再发出真正的请求。如果不符合,则直接返回跨域报错。
预检请求如下:
成功的例子:
失败的例子:
Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header has a value 'http://192.168.1.1:8083' that is not equal to the supplied origin.
如果预检请求通过了,在一定时间内重复请求是不用再次发起预检请求。
为什么需要预检请求
那为什么需要预检请求呢?
发出预检请求针对的是非简单请求,这些非简单请求有可能会在服务器进行比较大的运算,增加负载,如果此时cors不通过,就有可能增加了服务器没有必要的运算,如果此时有预检请求,如果不通过,则真实请求不会发出,在一定程度上减少了服务器无效的运算。
那为什么简单请求不需要预检呢?
因为简单请求可以由form表单发起,它不是ajax请求,不涉及到跨域和cors问题,可以直接与服务器通信,另外,简单请求大部分上是获取资源比较多,运算也没那么复杂,所以进行一次预检请求就没有必要。