为什么有些HTTP会先发出options请求

2,330 阅读2分钟

一、前言

在日常开发中,我们可能会偶尔看到在同样的一个接口请求了两次,而第一次请求的类型是options类型。检查了代码发现这个请求并不是由我们开发人员自己发起的,这是浏览器的行为。那么,为什么会有这样的请求呢。

二、options请求的作用

options请求其实是发生在跨域访问的时候的,跨域资源访问通过一种机制来检查服务器是否会允许要发送的真实请求,该机制通过浏览器发起一个到服务器托管的跨源资源的"预检"请求。在预检中,浏览器发送的头中标示有HTTP方法和真实请求中会用到的头。

三、什么时候会发生options请求

HTTP跨域请求里面,不是所有的请求都会发生options请求。满足以下条件的请求称之为简单请求,不会触发options:

  • 使用下列方法之一: GET
    HEAD
    POST
  • 除了被用户代理自动设置的首部字段(例如 Connection ,User-Agent)和在 Fetch 规范中定义为 禁用首部名称 的其他首部,允许人为设置的字段为 Fetch 规范定义的 对 CORS 安全的首部字段集合。该集合为:
    Accept
    Accept-Language
    Content-Language
    Content-Type (需要注意额外的限制)
    DPR
    Downlink
    Save-Data
    Viewport-Width
    Width
    Content-Type 的值仅限于下列三者之一:
    text/plain
    multipart/form-data
    application/x-www-form-urlencoded
  • 请求中的任意XMLHttpRequestUpload 对象均没有注册任何事件监听器;
    XMLHttpRequestUpload 对象可以使用 XMLHttpRequest.upload 属性访问。
  • 请求中没有使用 ReadableStream 对象。

不满足上述条件的跨域,都会发生options请求,因为浏览器不确定这些请求是会对服务器造成不可预知的影响。同时,在发出options请求的时候,需要服务器返回相应的头部才可进行真实的请求。

我们常见的会发生options请求的场景主要是以下这些:

  • 使用get/post/head 请求方法
    Put、Delete、Trace、Connect
    服务器需要返回Access-Control-Allow-Methods: POST, GET, OPTIONS
  • 使用了自定义的HTTP头部或不在上面范围的头部
    setRequestHeader('X-PINGOTHER', 'pingpong');
    服务器需要返回Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
  • contentType 不符合三者之一
    setRequestHeader('Content-Type', 'application/xml'); 服务器需要返回Access-Control-Allow-Headers: Content-Type
  • 携带了身份信息的请求
    withCredentials = true;
    服务器需要返回Access-Control-Allow-Credentials: true

以上就是关于options请求的一些解释

参考

跨源资源共享(CORS)
cors-safelisted-request-header