Ajax中跨域请求为什么触发Options请求?

浏览器将CORS请求分为两类:简单请求(simple request)和非简单请求(not-simple-request)。
简单请求浏览器请求不会触发预检请求,而非简单请求会触发预检请求

Ajax请求是由XMLHttpRequest对象实现的(部分低版本ID浏览器不是), 而XMLHttpRequest会遵守同源策略.也即脚本只能访问相同协议/相同主机名/相同端口的资源, 如果要突破这个限制, 那就是所谓的跨域, 此时需要遵守CORS(Cross-Origin Resource Sharing)机制.
简单粗暴实现跨域: 后台Access-Control-Allow-Origin: *
但是: 还一种叫请求叫Preflighted Request(带预检的跨域请求:由options发出)

发送一个方法为OPTIONS的预请求(Preflighted Request), 用于试探服务端是否能接受真正的请求.
如果options获得的回应是拒绝性质的,比如404\403\500等http状态,就会停止post、get等请求的发出。

问题来了: 什么情况下请求会变成Preflighted Request呢?

*1. 请求方法不是`GET/HEAD/POST`;
2. HTTP请求头限制这几种字段,`人为设置该集合之外 `的其他首部字段:
    `{Accept、Accept-Language、Content-Language、
    Content-Type(需要注意额外的限制)、
    DPR、Downlink、Save-Data、Viewport-Width、Width}`;
*3. POST请求的`Content-Type`并非:
    `{
      application/x-www-form-urlencoded, 
      multipart/form-data, 
      text/plain
    }`;
4. 请求中的任意 `XMLHttpRequestUpload` 对象均有注册事件监听器;
*5. 请求设置了自定义的 `header` 字段;
6. 请求中没有使用 `ReadableStream` 对象;

PS: 发送POST请求:content-type: text/xml 或者application/json,就会发送OPTIONS预请求;或者自定义header信息: 用户登录的token信息放入header里面,也会触发。

大部分跨域发送的请求都是非简单请求,如何减少发起OPTIONS请求的次数?

  1. 后端在请求的返回头部添加:Access-Control-Max-Age:(number)
    number代表:preflight request (预检请求)的返回结果可以被缓存多久,单位是。(即 Access-Control-Allow-Methods 和Access-Control-Allow-Headers 提供的信息)

例如:将预检请求的结果缓存1分钟:Access-Control-Max-Age: 60

不同浏览器有不同的上限。在Firefox中,上限是24h(即86400秒),而在Chromium 中则是10min(即600秒)。Chromium 同时规定了一个默认值 5 秒。

如果值为 -1,则表示禁用缓存,每一次请求都需要提供预检请求,即用OPTIONS请求进行检测。

Access-Control-Max-Age方法对完全一样的url的缓存设置生效,多一个参数也视为不同url。也就是说,如果设置了10分钟的缓存,在10分钟内,所有请求第一次会产生options请求,第二次以及第二次以后就只发送真正的请求了。

你可能感兴趣的:(Ajax中跨域请求为什么触发Options请求?)