Skip to content

HTTP 的 OPTIONS 预检请求:浏览器替你先去"敲门问一句"

更新: 6/28/2026 字数: 0 字 时长: 0 分钟

OPTIONS 预检请求封面

一句话先说清楚:OPTIONS 预检请求,是浏览器在发送某些跨域请求之前,自动先帮你向服务器"问一句能不能发"的安全确认动作。 服务器说"可以",浏览器才发真正的请求;服务器说"不行",真正的请求根本不会发出去。这个过程你写代码时不用手动触发,是浏览器自动加上的。

下面分点讲透。

一、什么是 OPTIONS 预检

  • OPTIONS 是 HTTP 的一种请求方法,和 GET、POST 并列。它的作用是"询问":问服务器对某个接口支持哪些操作、允不允许当前这个跨域请求。
  • "预检(Preflight)"的意思是正式请求之前的探路。好比你要进一栋楼办事,先派人去前台问:"我等下要送这么个东西进来,行不行?"前台同意了,你才真的把东西送进去。
  • 关键点:它是浏览器自动发起的,前端代码里看不到、也不用写。你只管调 fetchaxios,浏览器判断需要预检时,会自己先发一个 OPTIONS。

二、为什么需要它

这要从浏览器的安全机制"同源策略"说起。

  • 浏览器默认禁止网页向不同源(域名、端口、协议不同)的服务器随便发请求,防止恶意网站偷偷拿你的数据。这就是跨域限制。
  • 但实际开发中,前端和后端经常不同源(比如前端 a.com,接口在 api.b.com),需要合法跨域,于是有了 CORS(跨域资源共享) 机制来"开口子"。
  • 问题在于:有些请求一旦发出去就可能改数据(比如删除、修改)。如果等请求发到服务器才发现"不允许跨域",破坏已经造成了。
  • 所以浏览器对这类有潜在风险的请求,先发一个无害的 OPTIONS 去问:你允许我用 DELETE 方法吗?允许我带这个自定义请求头吗?服务器确认允许,才放行真正的请求。预检的本质,就是把风险挡在真正操作发生之前。

三、什么时候会触发

简单请求与需要预检的请求

不是所有跨域请求都预检。浏览器把请求分成两类:

简单请求——不预检,直接发:

同时满足以下条件才算简单请求:

  • 方法是 GETPOSTHEAD
  • 请求头只用了几个安全的默认头(如 AcceptContent-Type 等基础头);
  • Content-Type 只能是 text/plainapplication/x-www-form-urlencodedmultipart/form-data 这三种之一。

需要预检的请求——先发 OPTIONS:

只要触碰下面任意一条,就会触发预检:

  • 用了 PUTDELETEPATCH 等方法;
  • Content-Typeapplication/json(这是前端最常踩到的一条——现在传 JSON 几乎是标配,所以大量接口都会预检);
  • 带了自定义请求头,比如 AuthorizationtokenX-Requested-With 等。

实际开发中你会发现:明明只调了一个接口,Network 面板里却出现两条记录,第一条是 OPTIONS。这就是预检,属于正常现象,不是 bug。

四、完整请求流程

OPTIONS 预检完整流程

以一个跨域的 DELETE 请求为例,完整走两个来回:

第一步:浏览器发预检(OPTIONS)

浏览器自动发出 OPTIONS 请求,关键带上两个头告诉服务器"我接下来想干嘛":

http
OPTIONS /api/user/123 HTTP/1.1
Origin: https://a.com
Access-Control-Request-Method: DELETE
Access-Control-Request-Headers: Authorization

意思是:"我来自 a.com,想用 DELETE 方法、带 Authorization 头访问,行吗?"

第二步:服务器回应允许范围

服务器返回响应(通常状态码 204 或 200),用一组头表态:

http
Access-Control-Allow-Origin: https://a.com
Access-Control-Allow-Methods: GET, POST, DELETE
Access-Control-Allow-Headers: Authorization
Access-Control-Max-Age: 600

意思是:"允许 a.com,允许这些方法和这个头,并且这个许可你可以缓存 600 秒。"

第三步:预检通过,发真正的请求

浏览器看到允许范围覆盖了自己的需求,才发出真正的 DELETE 请求。

第四步:服务器返回真正的业务数据

这一步才真正执行删除并返回结果。

如果第二步服务器没返回正确的允许头,浏览器判定预检失败,真正的请求不会发出,前端会收到 CORS 报错。

五、常见相关要点

  • 预检结果可以缓存:服务器返回的 Access-Control-Max-Age 指定缓存时长,在这段时间内,同样的跨域请求不再重复发 OPTIONS,减少性能开销。
  • OPTIONS 请求不带业务数据:它只是"问路",不携带请求体、也不会触发服务器的业务逻辑。
  • 后端要正确处理 OPTIONS:如果后端没对 OPTIONS 方法放行或没配 CORS 头,预检就过不了。很多"跨域失败"问题根源在这里。
  • 预检失败 ≠ 接口本身有问题:经常是 CORS 配置不对,而不是业务接口写错了。排查时先看 OPTIONS 那条请求的响应头对不对。
  • 它带来轻微性能成本:多一次往返。所以能用简单请求的场景就别引入不必要的自定义头;高频接口可借助 Max-Age 缓存预检结果。

一句话总结

维度要点
是什么浏览器在跨域请求前自动发的 OPTIONS"问路"请求
为什么把风险挡在真正操作之前,配合 CORS 安全跨域
何时触发非简单请求:PUT/DELETE、application/json、自定义头
流程预检问 → 服务器答允许 → 通过才发真请求 → 返回数据
易错点后端没处理 OPTIONS / 没配 CORS 头,导致预检失败

简单记:OPTIONS 预检是浏览器的"先问后做",前端不用管,但后端必须配合放行,否则跨域请求会被卡在第一步。