前言:开发时设置手机代理抓接口请求时,打开H5页面,总是会看到OPTIONS请求,好奇跟常用的GET\POST有何不同,特此学习记录一下。
1. 作用
-
请求服务器返回所支持的所有HTTP请求方法;
示例:
$ curl -X OPTIONS http://example.org -i
HTTP/1.1 200 OK
Allow: OPTIONS, GET, HEAD, POST #
Cache-Control: max-age=604800
Content-Type: text/html; charset=UTF-8
Date: Thu, 14 Jul 2022 06:15:30 GMT
Expires: Thu, 21 Jul 2022 06:15:30 GMT
Server: EOS (vny/0453)
Content-Length: 0
响应报文包含一个 Allow
首部字段,该字段的值表明了服务器支持的所有 HTTP 方法。
-
跨域请求的预检请求;
下面👇🏻会详细介绍同源策略、跨域请求、OPTIONS请求。
2. 跨域请求
2.1 同源策略
如果两个URL的协议、主机、端口都相同,则称这两个URL同源。以http://music.javaswing.cn/home/index.html为例:
作用:这种同源策略,主要是限制html或者它加载的js如何和另一个源的资源进行交互,它能帮助阻隔恶意html,减少可能被攻击的媒介。
2.2 CORS(Cross Origin Resource Sharing) 跨域资源共享
CORS 跨域资源共享是一种机制,使用额外的HTTP头告诉浏览器,让运行在一个origin上的web应用被准许访问来自不同源服务器上的指定的资源。当一个资源从与该资源本身所在的服务器不同的域、协议、或端口请求一个资源时,资源会发起一个跨域HTTP请求。
简单来说,就是允许在https://www.aa.com/a/a.html的网页中,去请求https://www.bb.com/bb的接口获取数据。
3. OPTIONS预检请求
3.1 OPTIONS预检请求的触发条件
上面了解了同源策略和CORS,终于到了OPTIONS请求。在CORS机制下一个域名A要访问域名B的服务,在使用非简单请求之前,会先进行一个预检请求(浏览器自动发起),检查B服务是否允许跨域请求,服务确认之后,才会发起真正的HTTP请求。
同时,在预检请求的返回中,服务端也可以通知客户端,是否需要携带身份凭证(包括Cookies和HTTP认证相关数据)。
非简单请求:
- 请求方法为:
PUT/DELETE/CONNECT/OPTIONS/TRACE/PATCH
; - 设置了首部字段,不包括
Accept/Accept-Language/Content-Language/Content-Type/DPR/Downlink/Save-Data/Viewport-Width/Width
; -
Content-Type
值不属于application/x-www-form-urlencoded、multipart/form-data、text/plain
任何一个;
3.2 OPTIONS预检请求结构
3.2.1 OPTIONS预检请求头
OPTIONS预检请求会携带几个关键的Request Header:
Request Header | 作用 |
---|---|
Access-Control-Request-Method | 告诉服务器实际请求所使用的 HTTP 方法 |
Access-Control-Request-Headers | 告诉服务器实际请求所携带的自定义首部字段 |
Origin | 发起请求的域名 (协议、域名、端口号) |
{
"Host": "app.aaa.com",
"Origin": "https://m.bbb.com",
"Access-Control-Request-Method": "GET",
"Access-Control-Request-Headers": "csrf-token",
"Connection": "keep-alive",
"Accept": "*/*",
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 zzhunter",
"Referer": "https://m.caihuoxia.com/",
"Accept-Language": "zh-CN,zh-Hans;q=0.9",
"Accept-Encoding": "gzip"
}
3.2.2 OPTIONS预检响应头
预检响应头的关键字段:
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-Allow-Headers | 客户端请求所携带的自定义首部字段 |
{
"Server": "Tengine",
"Date": "Thu, 14 Jul 2022 06:25:07 GMT",
"Content-Type": "text/plain; charset=utf-8",
"Content-Length": "0",
"Connection": "keep-alive",
"Access-Control-Allow-Origin": "https://m.bbb.com",
"Access-Control-Allow-Credentials": "true",
"Access-Control-Allow-Headers": "PPU,t,tk,v,uid,Content-Type,Csrf-Token",
"Access-Control-Allow-Methods": "GET,POST,OPTIONS",
"Access-Control-Max-Age": "1728000",
"Set-Cookie": [
"id58=c5/nR2LPtsOJbsB8a+YHAg==; expires=Sat, 13-Jul-24 06:25:07 GMT; domain=caihuoxia.com; path=/"
],
"P3P": "policyref=\"/w3c/p3p.xml\", CP=\"CUR ADM OUR NOR STA NID\""
}
4. OPTIONS预检请求优化
上面了解到,跨域请求会触发两次请求:OPTIONS预检请求、真正的请求。可以通过缓存OPTIONS预检请求的结果,来减少请求的数量。
Access-Control-Max-Age
这个响应首部表示预检请求的返回结果(即 Access-Control-Allow-Methods
和 Access-Control-Allow-Headers
提供的信息) 可以被缓存的最长时间,单位是秒。
如果值为 -1,则表示禁用缓存,每一次请求都需要提供预检请求,即用 OPTIONS 请求进行检测。
5. 总结
OPTIONS预检请求,可用于检测服务器允许的http方法。另外,当发起跨域请求时,非简单请求会导致浏览器自动发起一次OPTIONS预检请求,服务器接受该跨域请求之后,浏览器才继续发起正式请求。
网友评论