起因
最近写项目的时候,发现前端中的请求发送了两遍,同时也看到了options请求。

前置知识
HTTP常见的请求
1.get:参数在url上,浏览器长度有限制,不安全
2.post:参数不可见,长度不受限制
3.put:上传最新内容到指定位置
4.delete:删除请求的url所表示的资源
5.head:不返回相应主体,主要用于客户端查看服务器性能
6.options:与head类似,是客户端用于查看服务器的性能 。JavaScript的XMLHttpRequest对象进行CORS跨域资源共享时,就是使用OPTIONS方法发送嗅探请求,以判断是否有对指定资源的访问权限
7.connect:http1.1预留的,将连接方式改为管道方式,通常用于SSL加密服务器的链接与 HTTP非加密的代理服务器之间的通信
8.trace:请求服务器[回显收到的请求信息]主要用于HTTP请求的测试或诊断
9.patch:出现的较晚,用于更新局部的资源,不存在时,会创建一个新的(http1.1之后使用的较多的)
预请求
预请求就是复杂请求(可能对服务器数据产生副作用的HTTP请求方法,如put,delete都会对服务器数据进行更修改,所以要先询问服务器)。
在MDN的规范中规定,对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求),浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。
分析
第一次请求

第一次请求中,在浏览器里看到请求request header 和 response header的信息如下:
Request Header | 作用 |
---|---|
Access-Control-Request-Method | 告诉服务器实际请求所使用的 HTTP 方法 |
Access-Control-Request-Headers | 告诉服务器实际请求所携带的自定义首部字段,本次实际请求首部字段中content-type为自定义 |
服务器基于从预检请求头部获得的信息来判断,是否接受接下来的实际请求。
在浏览器里看到的预检响应头response header的关键字段:
Response header | 作用 |
---|---|
Access-Control-Allow-Methods | 返回了服务端允许的请求,包含GET/HEAD/PUT/PATCH/POST/DELETE |
Access-Control-Allow-Credentials | 允许跨域携带cookie(跨域请求要携带cookie必须设置为true) |
Access-Control-Allow-Origin | 允许跨域请求的域名,这个可以在服务端配置一些信任的域名白名单 |
Access-Control-Request-Headers | 客户端请求所携带的自定义首部字段content-type |

注:此次OPTIONS请求返回了响应头的内容,但没有返回响应实体response body内容。

第二次请求
这是本来要发送的请求,如图所示是普通的post请求。其中Content-Type的application/json是此次和后端约定的请求内容格式。

什么时候发生预请求
上面已经说了在什么情况下会发生预请求,这里在总结下:
- (1) 请求方法不是以下三种方法之一:
GET,Head,Post - (2)HTTP的头信息超出以下几种字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:不这三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
options作用
OPTIONS请求方法的主要用途有两个:
获取服务器支持的HTTP请求方法;也是黑客经常使用的方法。
用来检查服务器的性能。例如:AJAX进行跨域请求时的预检,需要向另外一个域名的资源发送一个options请求头,用以判断实际发送的请求是否安全。
总结
这里涉及到跨域知识,请参考
跨域资源共享CORS
跨域资源共享 CORS 详解
前端常见跨域解决方案(全)
网友评论