面试官:如何减少 options 请求

2,039 阅读6分钟

在找工作的伙伴,可以看看这里:双越老师联合几位博主(包括我)搞了一个前端面试网站 面试派 —— 常见面试题 + 大厂面试流程 + 面试技巧。做一个真正专业的前端面试网站,旨在解决前端面试资料碎片化、老旧化、非专业化等一系列问题,网站开源免费且持续更新题库!

想要回答这个问题需要先明白什么是简单请求和非简单请求

浏览器请求方式可以划分为简单请求和非简单请求

简单请求

简单请求你可以理解为那些不会对服务器造成风险的请求。根据 CORS(跨源资源共享,Cross-Origin Resource Sharing) 的定义,简单请求必须满足以下条件:

  • 使用 GETPOSTHEAD 方法。
  • 仅包含少量特定的请求头部,如 AcceptAccept-LanguageContent-LanguageContent-Type(但只能是 application/x-www-form-urlencodedmultipart/form-datatext/plain)。
  • 不包含自定义的请求头部(即除了浏览器默认的上面那些)。

非简单请求

不满足简单请求的条件就是非简单请求

除了 GETPOST 和 HEAD 之外的其他 HTTP 方法都会导致请求变成非简单请求,例如:

  • PUT
  • DELETE
  • PATCH

任何不在简单请求头部列表中的头部,或者 Content-Type 不是 application/x-www-form-urlencodedmultipart/form-data 或 text/plain 的情况,都会导致请求变成非简单请求。例如:

  • Authorization
  • X-Custom-Header
  • Content-Type: application/json

非简单请求之前通常会触发浏览器发送一个 OPTIONS 预检请求,以确保服务器允许该跨域请求。

因此 options 请求就是预检请求

预检请求(Preflight Request)的意义

一句话解释:预检请求是浏览器在执行某些跨域请求之前,先发送的一种特殊的 HTTP 请求。它的主要目的是确保安全性,这个安全性针对服务端和客户端,服务端是防止恶意请求对服务器造成潜在的风险,客户端是保护用户的安全和隐私

非简单请求之前,预检请求先来询问服务器能否跨个域,就像是去朋友家做客,先打个电话问是否方便

  1. 服务器是否允许跨域请求:通过预检请求,浏览器可以确认服务器是否允许来自不同域名的请求。
  2. 允许的请求方法:预检请求可以告诉浏览器,服务器允许哪些 HTTP 方法(如 GETPOSTPUT 等)。
  3. 允许的请求头部:预检请求可以告诉浏览器,服务器允许哪些自定义的请求头部。

跨域请求

跨域请求是指从一个域(如 http://example.com)向另一个域(如 http://another-domain.com)发送的 HTTP 请求。无论请求是简单请求还是非简单请求,只要涉及到不同的域名、端口或协议,就属于跨域请求。因此跨域是不分简单请求和非简单请求的

非简单请求的跨域处理(预检请求的工作流程)

  1. 发送预检请求

当浏览器检测到一个非简单请求时,会先发送一个 OPTIONS 请求到服务器,询问服务器是否允许该实际请求。这个预检请求包含以下信息:

  • 请求方法(如 PUTDELETE 等)
  • 请求头部(如 Content-TypeAuthorization 等)
  1. 服务器响应预检请求

服务器收到预检请求后,需要返回一个响应,告诉浏览器它是否允许这个跨域请求。响应中包含以下信息:

  • 允许的来源(Access-Control-Allow-Origin
  • 允许的方法(Access-Control-Allow-Methods
  • 允许的头部(Access-Control-Allow-Headers
  1. 发送实际请求

如果服务器允许该请求,浏览器才会继续发送实际的请求

  1. 服务器响应实际请求

服务器处理实际请求,并返回响应

即使是简单请求,如果是跨域的,浏览器仍然会进行一些安全检查,但不会发送预检请求。

回归本文主题,回答之前你是否好奇明明预检请求是为了确保服务器和用户的安全,为何还要减少它?

options 请求过多带来的问题

  • 性能损耗:OPTIONS 请求是额外的网络开销。虽然通常不会带来显著的性能问题,但在高流量的应用中,大量的 OPTIONS 请求可能会增加服务器负担和网络延迟。

  • 用户体验:虽然 OPTIONS 请求本身很快(通常是几 ms ),但如果它们频繁出现或处理缓慢,可能会间接影响用户体验。减少这些请求可以确保实际的业务请求更快地得到响应。

  • 服务器负担:每个 OPTIONS 请求都需要服务器进行处理,并返回相应的 CORS 头部。这可能会增加服务器的负担,尤其是在处理大量预检请求时。优化这些请求有助于减少服务器的计算和网络开销。

如何减少 options 请求呢

  1. 尽量使用简单请求

从根源上看,浏览器不会对符合条件的 简单请求 发起 OPTIONS 预检请求,因此去使用简单请求

  1. 限制使用自定义头部

为了避免触发 OPTIONS 请求,尽量避免在请求中使用自定义头部。自定义头部会使请求成为非简单请求,从而触发 OPTIONS 预检请求。

  1. 使用 Content-Type 限制

如果你使用 POST 请求,可以通过限制 Content-Type 头部来避免 OPTIONS 请求。允许的 Content-Type 包括:

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

如果你使用其他类型的 Content-Type,如 application/json,则会触发 OPTIONS 请求。

  1. 优化请求模式

尽量将请求方式设计得更简洁,避免复杂的跨域场景。如果可能,将请求合并为较少的 API 调用,减少跨域请求的次数。

  1. 服务器端配置

虽然前端没有直接控制 OPTIONS 请求,但在服务端,你可以通过优化 CORS 配置来处理 OPTIONS 请求。确保服务器对预检请求的响应快速且高效,以减少对前端性能的影响。

  1. 使用同域名资源

如果可以,尽量将前端和后端部署在同一域名下。这样可以避免跨域请求,完全不需要 OPTIONS 请求。

总结

想要减少 options 请求数量,主要可以通过确保请求满足简单请求的条件来避免预检请求,或者优化请求设计和头部使用

面试官问这个问题想必大部分人都是懵逼状态,因为你可能没有想过二次请求带来的问题,想要避免他就需要清楚 options 请求的发生条件

这是我的公众号:Dolphin海豚,不定期分享前端知识点,欢迎各路伙伴前来关注

另外有不懂之处欢迎在评论区留言,如果觉得文章对你学习有所帮助,还请 ”点赞+评论+收藏“ 一键三连,感谢支持!