跳转到内容

前端进阶:详解跨域请求中神秘的 OPTIONS 预检请求 ​

为什么浏览器有时候会发送一个 options 请求?有时候又没有?明明我们的代码中根本就没写options请求,它到底是在什么情况下才会出现?

先说一个结论:OPTIONS 请求是「浏览器专用」、且「自动发送」的。

一、什么时候浏览器会发 OPTIONS 请求? ​

很多人都误以为:只有 POST、PUT 请求才会发送 OPTIONS,GET 请求不会发送。

其实不是,只要满足了下面两个条件,就会触发 OPTIONS:

  • 跨域
  • 非简单请求

也是就:非简单请求跨域访问的时候,浏览器就会自动发送 OPTIONS 请求。

跨域我们都知道,就不多介绍了,那什么是非简单请求呢?

1. GET、POST、HEAD 之外的请求方法

只要不是这 3 个请求方法,都是非简单请求。

2. 自定义 Header

只要存在自定义的 Header,就是非简单请求。

ts
headers: {
  'cityId': 'beijing',
}

3. 非简单 Header

简单请求的 Header 只允许以下这些信息:

txt
Accept
Accept-Language
Content-Language
Content-Type(只能是下面 3 种值)

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

只要包含除此之外的信息,都是非简单请求。

TIP

比如:我们经常使用的application/json,就是非简单请求。

4. 携带凭证

ts
fetch(url, {
  credentials: 'include',
})

二、浏览器为什么要发送 OPTIONS 请求? ​

OPTIONS 请求也就是我们常说的预检请求(Preflight),

20251231094305_image.png

浏览器在发送跨域请求之前,会先询问服务器:

我等下要发送这个方法、这些 HEADER,你是否允许?

这个询问的请求就是 OPTIONS 请求。

如果服务器没有允许,浏览器就会直接中断这个跨域请求。

浏览器为什么要这么做?其实还是为了安全。

试想一下,如果一个恶意的网站,拿到了用户的登录态后,随意地做一些事情是非常危险的。

有了预检请求,浏览器会在做这些操作之前,先询问浏览器:

  • 这个 origin (请求来源站点)是否允许?
    http
    Access-Control-Allow-Origin: https://example.com
  • 这个请求方法是否允许?
    http
    Access-Control-Allow-Methods: POST, PUT, DELETE
  • 这些 header 是否允许?
    http
    Access-Control-Allow-Headers: Content-Type, Authorization
  • 是否允许携带凭证?
    http
    Access-Control-Allow-Credentials: true

如果服务器拒绝,浏览器就不会发送正式的请求操作,从而保证了安全性。

三、服务端如何处理? ​

现在我们知道:OPTIONS 请求是浏览器行为,它是在跨域、非简单请求发起之前,先向服务器进行确认。

所以,服务端要处理 OPTONS,通常都会在业务代码之前进行处理,来告诉浏览器我能接受哪些跨域的请求。

ts
if (request.method === 'OPTIONS') {
  return new Response(null, {
    status: 204,
    // 设置允许的 origin、method、Header
    headers: {
      'Access-Control-Allow-Origin': 'http://localhost:3000',
      'Access-Control-Allow-Methods': 'GET,POST,OPTIONS',
      'Access-Control-Allow-Headers': 'Content-Type, Authorization',
    },
  })
}

// 正常业务代码

浏览器在接收到 OPTIONS 请求的响应头信息后,就会判断服务器是否允许发送接下来的请求。

如果服务器不处理 OPTIONS 会怎样?

对浏览器来说,只要没得到服务器明确的答复,就不会发送后面正式的请求。所以,服务器必须同时在 OPTIONS 和原本请求上都要加上对应的跨域 Header 信息。

为什么 OPTIONS 返回的状态码是 204?

因为浏览器只关心 OPTIONS 返回的 Header 信息,不关心其内容。204 表示 No Content 正好符合此语义(非强制)。

最后总结 ​

在跨域、非简单请求发起之前,浏览器会自动发送 OPTIONS 请求,先向服务器确认是否允许。

所以,OPTIONS 其实是浏览器在帮你做安全确认,不要搞错了哦。