你知道什么是预检请求吗?

3,587 阅读2分钟

这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战

问题

上一篇文章讲了解决跨域请求的几种方式,第一种方式是cors,趁热打铁,今天顺便来学习下cors下的预检请求,学习这个概念对我们排查网络请求的时候会有帮助。

概念

cors,把请求分为2种

  • 简单请求(simple request)
  • 非简单请求 (preflight request),请求方法是OPTIONS

那区分二者的标准是什么? 如下:

  • 请求的方法只能是GET, POST, HEAD的一种
  • 请求的header的只能是AcceptAccept-Language, Content-LanguageContent-Type这些字段,不能超出这些字段
  • 对于请求的header的Content-Type字段,只能是以下值
    • text/plain
    • multipart/form-data
    • application/x-www-form-urlencoded

都满足以上条件的就是简单请求,否则就是非简单请求。

比如我们经常使用的Content-Type:application/json; charset=utf-8,这个请求就是非简单请求

流程

如果是简单请求,则浏览器会直接向目标服务器发出请求,如果请求符合cors的配置,则返回结果。

但是如果不是简单请求,浏览器会在发出真正请求前,先发出预检请求,检查当前请求是否符合服务器的cors配置,如果符合,则再发出真正的请求。如果不符合,则直接返回跨域报错。

预检请求如下:

image.png

成功的例子: image.png

失败的例子:

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问题,可以直接与服务器通信,另外,简单请求大部分上是获取资源比较多,运算也没那么复杂,所以进行一次预检请求就没有必要。