Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
WangXiZhu opened this issue Jul 25, 2019 · 1 comment

Comments

@WangXiZhu
Copy link
Owner

image

@WangXiZhu
Copy link
Owner Author

WangXiZhu commented Jul 25, 2019

贴出请求代码

   $.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下有有两条请求!

更多

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant