options请求,简单请求,非简单请求

2,255 阅读5分钟

OPTIONS请求

有时我们在浏览器中发现发送的ajax请求自动请求两次,第一次是options请求,第二次才是你自己发送的get或post请求。

什么是options请求

OPTIONS请求方法的主要用途有两个:

  1. 获取服务器支持的HTTP请求方法;

  2. 用来检查服务器的性能。例如:AJAX进行跨域请求时的预检,需要向另外一个域名的资源发送一个HTTP OPTIONS请求头,用以判断实际发送的请求是否安全。

这是浏览器给我们加上的,后端并没有做任何操作

为什么要用到options请求

OPTIONS请求旨在发送一种“探测”请求以确定针对某个目标地址的请求必须具有怎样的约束(比如应该采用怎样的HTTP方法以及自定义的请求报头),然后根据其约束发送真正的请求。比如针对“跨域资源”的预检(Preflight)请求采用的HTTP方法就是OPTIONS。

CORS

详细阅读:www.ruanyifeng.com/blog/2016/0…

分类

浏览器将CORS分为简单请求非简单请求

  1. 同时满足以下两个条件,就是简单请求:
  • 请求方法是以下三种方法之一:

  • HTTP的头信息不超出以下几种字段:

    • Accept
    • Accept-Language
    • Content-Language
    • Last-Event-ID
    • Content-Type:只限于三个值application/x-www-form-urlencodedmultipart/form-datatext/plain三种content-type
      • application/x-www-form-urlencoded: 表示使用URL编码的方式来编码表单。如果没有将enctype属性设置为任何值,那么这就是默认值
      • multipart/form-data: 当用户想上传文件这种二进制等文件或者前面的那个方式不能满足时,使用这种类型的表单
      • text/plain: 文本形式,只发送数据而不进行任何编码时使用
  1. 凡是不同时满足上面两个条件,就属于非简单请求。
  2. 浏览器对这两种请求的处理,是不一样的。

简单请求的处理

  1. 对于简单请求,浏览器直接发出CORS请求。具体来说,就是在头信息之中,增加一个Origin字段
  • 例子
GET /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
  • Origin字段用来说明,本次请求来自哪个源(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求。
  • 如果Origin指定的源,不在许可范围内,服务器会返回一个正常的HTTP回应。浏览器发现,这个回应的头信息没有包含Access-Control-Allow-Origin字段(详见下文),就知道出错了,从而抛出一个错误,被XMLHttpRequestonerror回调函数捕获。注意,这种错误无法通过状态码识别,因为HTTP回应的状态码有可能是200
  • 如果Origin指定的域名在许可范围内,服务器返回的响应,会多出几个头信息字段。
Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8

非简单请求的处理

  1. 非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUTDELETE,或者Content-Type字段的类型是application/json
  2. 非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)
  3. 浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。
  4. "预检"请求用的请求方法是OPTIONS,表示这个请求是用来询问的。头信息里面,关键字段是Origin,表示请求来自哪个源。
  5. 如果服务器否定了"预检"请求,会返回一个正常的HTTP回应,但是没有任何CORS相关的头信息字段。这时,浏览器就会认定,服务器不同意预检请求,因此触发一个错误,被XMLHttpRequest对象的onerror回调函数捕获。
  6. 一旦服务器通过了"预检"请求,以后每次浏览器正常的CORS请求,就都跟简单请求一样,会有一个Origin头信息字段。服务器的回应,也都会有一个Access-Control-Allow-Origin头信息字段。

总结

跨域CORS的非简单请求,通过options做预检查,用以判断实际发送的请求是否安全

  1. OPTIONS请求方法的主要用途有两个:

    1. 获取服务器支持的HTTP请求方法;

    2. 用来检查服务器的性能。例如:AJAX进行跨域请求时的预检,需要向另外一个域名的资源发送一个HTTP OPTIONS请求头,用以判断实际发送的请求是否安全。

  2. 规范要求,对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求),浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。

  3. “需预检的请求”要求必须首先使用 OPTIONS 方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求。

  4. 当请求满足下述任一条件时(非简单请求),即应首先发送预检请求(使用OPTIONS):

    1. 使用了下面任一 HTTP 方法:

      • PUT
      • DELETE
      • CONNECT
      • OPTIONS
      • TRACE
      • PATCH
    2. 人为设置了对 CORS 安全的首部字段集合之外的其他首部字段。该集合为:

      • Accept
      • Accept-Language
      • Content-Language
      • Content-Type (but note the additional requirements below)
      • DPR
      • Downlink
      • Save-Data
      • Viewport-Width
      • Width
    3. Content-Type 的值不属于下列之一:

      • application/x-www-form-urlencoded
      • multipart/form-data
      • text/plain

为什么有options