WangXiZhu / fe-storage

这是平时自己的学习资料
0 stars 2 forks source link

每日1问-chrome面板里面同一个链接发了两次请求。请求方式分别是OPTIONS和GET #31

Open WangXiZhu opened 5 years ago

WangXiZhu commented 5 years ago

image

WangXiZhu commented 5 years ago

贴出请求代码

   $.ajax({
      url: url,
      type: 'GET',
      data: {},
      // 通过设置header: xhrFields是错误的方式。但这次错误能了解OPTIONS请求的缘由
      // headers: {
        // xhrFields: true
      // },
      xhrFields: {
          withCredentials: true
      },
      success: function(res){
       // do something
      }
    })

表面差异

先从表象看看区别[上面两个请求分别以OPTIONS请求GET请求区分]

  1. initiator OPTIONS请求是通过Script发送; GET请求是通过Parser发送;

Parser:请求是由页面的HTML解析时发送的; Redirect:请求是由页面重定向发送的; Script:请求是由script脚本处理发送的; Other:请求是由其他过程发送的,比如页面里的link链接点击,在地址栏输入URL地址。

  1. Response Headers 和 Request Headers
Headers Request Response
OPTIONS Access-Control-Request-Headers: xhrfields
Access-Control-Request-Method: GET
Sec-Fetch-Mode: no-cors
content-length: 0
GET Sec-Fetch-Mode: cors
xhrFields: true
content-encoding: gzip
content-type: application/json;charset=UTF-8

image

image

OPTIONS的作用

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

注意到OPTIONS请求的Request Header中有Access-Control-Allow-HeadersAccess-Control-Request-Method,其中Access-Control-Allow-Headers的值为xhrfields

而Access-Control-Allow-Headers的作用是通知服务器在真正的请求中会采用哪些请求首部。

请求首部 Access-Control-Request-Headers 出现于 preflight request (预检请求)

Preflight request(预检请求)

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

所以即使我们没有写这样的代码,这条OPTIONS请求还是发送出去了

难道每次ajax请求都会发送两个请求吗?(PS:Preflight request产生的条件)

  1. 请求方法不是GET/HEAD/POST
  2. POST请求的Content-Type并非application/x-www-form-urlencoded, multipart/form-data, 或text/plain
  3. 请求设置了自定义的header字段

我们这里是设置了header,所以发了一条Preflight request

AJAX与CORS

image

Initiator中标记了OPTIONS请求的js堆栈,zepto.js最后直接与XMLHttpRequest关联

  1. zepto的ajax请求是对XMLHttpRequest(非IE10以下)的封装,则依赖XMLHttpRequest

  2. XMLHttpRequest 遵守同源策略

  3. 如果要跨域请求资源的话需要遵守CORS

总结

跨域请求中设置了自定义的header字段 xhrFields, 所以该请求是preflighted request, 则请求前一定会发送一个OPTIONS作为预请求。所以chrome下有有两条请求!

更多