想要回答这个问题需要先明白什么是简单请求和非简单请求
浏览器请求方式可以划分为简单请求和非简单请求
简单请求
简单请求你可以理解为那些不会对服务器造成风险的请求。根据 CORS(跨源资源共享,Cross-Origin Resource Sharing) 的定义,简单请求必须满足以下条件:
使用
GET
、POST
或HEAD
方法。仅包含少量特定的请求头部,如
Accept
、Accept-Language
、Content-Language
、Content-Type
(但只能是application/x-www-form-urlencoded
、multipart/form-data
或text/plain
)。不包含自定义的请求头部(即除了浏览器默认的上面那些)。
非简单请求
不满足简单请求的条件就是非简单请求
除了
GET
、POST
和HEAD
之外的其他 HTTP 方法都会导致请求变成非简单请求,例如:
PUT
DELETE
PATCH
任何不在简单请求头部列表中的头部,或者
Content-Type
不是application/x-www-form-urlencoded
、multipart/form-data
或text/plain
的情况,都会导致请求变成非简单请求。例如:
Authorization
X-Custom-Header
Content-Type: application/json
非简单请求之前通常会触发浏览器发送一个 OPTIONS
预检请求,以确保服务器允许该跨域请求。
因此 options 请求就是预检请求
预检请求(Preflight Request)的意义
一句话解释:预检请求是浏览器在执行某些跨域请求之前,先发送的一种特殊的 HTTP 请求。它的主要目的是确保安全性,这个安全性针对服务端和客户端,服务端是防止恶意请求对服务器造成潜在的风险,客户端是保护用户的安全和隐私
非简单请求之前,预检请求先来询问服务器能否跨个域,就像是去朋友家做客,先打个电话问是否方便
服务器是否允许跨域请求:通过预检请求,浏览器可以确认服务器是否允许来自不同域名的请求。
允许的请求方法:预检请求可以告诉浏览器,服务器允许哪些 HTTP 方法(如
GET
、POST
、PUT
等)。允许的请求头部:预检请求可以告诉浏览器,服务器允许哪些自定义的请求头部。
跨域请求
跨域请求是指从一个域(如 http://example.com
)向另一个域(如 http://another-domain.com
)发送的 HTTP 请求。无论请求是简单请求还是非简单请求,只要涉及到不同的域名、端口或协议,就属于跨域请求。因此跨域是不分简单请求和非简单请求的
非简单请求的跨域处理(预检请求的工作流程)
发送预检请求
当浏览器检测到一个非简单请求时,会先发送一个 OPTIONS
请求到服务器,询问服务器是否允许该实际请求。这个预检请求包含以下信息:
请求方法(如
PUT
、DELETE
等)请求头部(如
Content-Type
、Authorization
等)
服务器响应预检请求
服务器收到预检请求后,需要返回一个响应,告诉浏览器它是否允许这个跨域请求。响应中包含以下信息:
允许的来源(
Access-Control-Allow-Origin
)允许的方法(
Access-Control-Allow-Methods
)允许的头部(
Access-Control-Allow-Headers
)
发送实际请求
如果服务器允许该请求,浏览器才会继续发送实际的请求
服务器响应实际请求
服务器处理实际请求,并返回响应
即使是简单请求,如果是跨域的,浏览器仍然会进行一些安全检查,但不会发送预检请求。
回归本文主题,回答之前你是否好奇明明预检请求是为了确保服务器和用户的安全,为何还要减少它?
options 请求过多带来的问题
性能损耗:
OPTIONS
请求是额外的网络开销。虽然通常不会带来显著的性能问题,但在高流量的应用中,大量的OPTIONS
请求可能会增加服务器负担和网络延迟。用户体验:虽然
OPTIONS
请求本身很快(通常是几 ms ),但如果它们频繁出现或处理缓慢,可能会间接影响用户体验。减少这些请求可以确保实际的业务请求更快地得到响应。服务器负担:每个
OPTIONS
请求都需要服务器进行处理,并返回相应的 CORS 头部。这可能会增加服务器的负担,尤其是在处理大量预检请求时。优化这些请求有助于减少服务器的计算和网络开销。
如何减少 options 请求呢
尽量使用简单请求
从根源上看,浏览器不会对符合条件的 简单请求 发起 OPTIONS
预检请求,因此去使用简单请求
限制使用自定义头部
为了避免触发 OPTIONS
请求,尽量避免在请求中使用自定义头部。自定义头部会使请求成为非简单请求,从而触发 OPTIONS
预检请求。
使用
Content-Type
限制
如果你使用 POST
请求,可以通过限制 Content-Type
头部来避免 OPTIONS
请求。允许的 Content-Type
包括:
application/x-www-form-urlencoded
multipart/form-data
text/plain
如果你使用其他类型的 Content-Type
,如 application/json
,则会触发 OPTIONS
请求。
优化请求模式
尽量将请求方式设计得更简洁,避免复杂的跨域场景。如果可能,将请求合并为较少的 API 调用,减少跨域请求的次数。
服务器端配置
虽然前端没有直接控制 OPTIONS
请求,但在服务端,你可以通过优化 CORS 配置来处理 OPTIONS
请求。确保服务器对预检请求的响应快速且高效,以减少对前端性能的影响。
使用同域名资源
如果可以,尽量将前端和后端部署在同一域名下。这样可以避免跨域请求,完全不需要 OPTIONS
请求。
总结
想要减少 options 请求数量,主要可以通过确保请求满足简单请求的条件来避免预检请求,或者优化请求设计和头部使用
面试官问这个问题想必大部分人都是懵逼状态,因为你可能没有想过二次请求带来的问题,想要避免他就需要清楚 options 请求的发生条件