什么是 HTTP Get + Preflight 请求

当在 Chrome 开发者工具的 Network 面板中看到 GET + Preflight 的 HTTP 请求方法时,意味着该请求涉及跨域资源共享 (CORS),并且该请求被预检了。理解这种请求的背景,主要在于 CORS 的工作机制和现代浏览器对安全性的管理。

下面是在 Chrome 开发者工具 Network 面板里观察到的例子:

什么是 CORS?

CORS 是 Cross-Origin Resource Sharing 的缩写,它是浏览器与服务器之间的一种安全机制,用于控制不同源(如不同域名、端口或协议)之间的 HTTP 请求。正常情况下,浏览器会禁止不同源之间的请求(称为同源策略)。然而,CORS 是一种打破同源策略的方式,允许服务器明确声明哪些源可以访问它的资源。

什么是 Preflight?

Preflight 是 CORS 机制中的一个关键概念。它是一个通过 OPTIONS 方法发出的请求,目的是在执行实际的跨域请求之前,浏览器询问服务器是否允许这个跨域操作。这种请求被称为"预检"请求。浏览器会发起 Preflight 请求,以确保实际的 GETPOST 等请求可以被安全执行。

预检请求主要是为了处理那些对服务器有潜在影响的"复杂"请求,例如:

  • 使用 PUTDELETE 方法。
  • 使用自定义的 HTTP 头。

下面是自定义 HTTP 请求头部的一个例子:

  • 发送 JSON 格式的数据。

通过预检,服务器可以回应是否允许该请求,并指定具体的允许条件,比如允许哪些 HTTP 方法、请求头或返回数据。

为什么会看到 GET + Preflight

当你看到 GET + Preflight,意味着浏览器在发起跨域的 GET 请求时,进行了一个预检请求,以确保服务器允许这个请求。预检请求用 OPTIONS 方法发送,服务器在响应时会指明是否允许后续的跨域请求。

举个例子,假设你有一个前端应用运行在 http://example.com,而它想要获取一个来自 http://api.example.com 的资源。如果浏览器认为这个请求是一个复杂请求,它就会先发起一个 OPTIONS 请求(即预检),并等待服务器确认是否允许该请求。

示例

场景描述

设想一个跨域 API 请求,前端应用试图从远程 API 获取数据:

javascript 复制代码
fetch('https://api.example.com/data', {
  method: 'GET',
  headers: {
    'X-Custom-Header': 'CustomValue'
  }
});

在这个例子中,由于使用了自定义头 X-Custom-Header,浏览器会认为这个请求是复杂的,因此需要执行 Preflight

预检请求

在这种情况下,浏览器会首先发送一个 OPTIONS 请求去探测目标服务器是否允许该请求。这是典型的预检请求:

http 复制代码
OPTIONS /data HTTP/1.1
Host: api.example.com
Origin: http://example.com
Access-Control-Request-Method: GET
Access-Control-Request-Headers: X-Custom-Header

服务器响应可能看起来像这样:

http 复制代码
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://example.com
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: X-Custom-Header

这意味着服务器允许来自 http://example.com 的跨域请求,支持 GET 方法,并且允许使用 X-Custom-Header 请求头。预检请求成功后,浏览器才会继续发送实际的 GET 请求。

一个实际的例子:

实际的 GET 请求

预检成功后,浏览器会发送最终的 GET 请求:

http 复制代码
GET /data HTTP/1.1
Host: api.example.com
Origin: http://example.com
X-Custom-Header: CustomValue

服务器响应:

http 复制代码
HTTP/1.1 200 OK
Content-Type: application/json
Access-Control-Allow-Origin: http://example.com
{
  "data": "example data"
}

在 Chrome 的 Network 面板中,你会看到这两个请求,分别是 OPTIONSGET。由于 PreflightGET 请求的一部分,所以你看到的请求被标记为 GET + Preflight

使用场合

GET + Preflight 这种情况经常发生在需要跨域请求并且请求较为复杂的场景中。比如:

  1. 前端应用与不同源的后端 API 通信。
  2. 微服务架构中,前端可能需要从不同的微服务中获取数据。
  3. 某些情况下,安全性考虑使得跨域资源访问变得更加严格,比如访问需要认证的资源。

假如没有 Preflight 机制,浏览器的同源策略会限制开发者对外部资源的访问,造成跨域请求无法正常进行。而 Preflight 提供了一个安全的方式,确保跨域请求在得到服务器许可的情况下才会被执行。

如何优化 Preflight 请求?

虽然 Preflight 提供了安全性保障,但额外的 OPTIONS 请求会增加请求的开销,尤其是在高频 API 请求的场景下。开发者可以通过以下方式优化:

  1. 减少复杂请求 :避免使用自定义的请求头,或者在不必要的情况下使用复杂的 HTTP 方法。比如,简单的 GETPOST 请求,不使用复杂的头部时,是不需要 Preflight 请求的。

  2. 服务器端优化 :通过设置 Access-Control-Max-Age 头,允许浏览器缓存 Preflight 的结果。例如:

    http 复制代码
    Access-Control-Max-Age: 600

    这表示浏览器可以在 600 秒内不必再次进行预检,从而减少了 Preflight 请求的频率。

  3. 同源策略优化:在架构设计中,尽量避免跨域请求,尤其是在应用内部组件之间通信时。比如,使用反向代理让所有服务运行在同一域下,避免触发 CORS 机制。

总结

GET + Preflight 请求是现代 Web 应用中非常常见的一部分,它代表了浏览器对跨域请求的安全管理。通过理解 CORS 及其预检机制,开发者可以更好地设计跨域 API 请求,优化应用的性能,同时确保安全性。

在复杂 Web 应用中,特别是 SPA(单页应用)和基于 API 的架构中,跨域请求频繁发生。Preflight 请求的存在可以确保这些跨域操作在安全的前提下进行,同时让开发者能够更灵活地设计前后端分离的架构。

相关推荐
CH_Qing1 小时前
【udev】关于/dev 设备节点的生成 &udev
linux·前端·网络
妮妮喔妮1 小时前
HTTP中常见的Content-Type
网络·网络协议·http
木鱼时刻1 小时前
网络基础知识与代理配置
网络
入眼皆含月1 小时前
Openssl升级
网络
危险、2 小时前
RabbitMQ 通过HTTP API删除队列命令
分布式·http·rabbitmq
超人不会飛2 小时前
就着HTTP聊聊SSE的前世今生
前端·javascript·http
数通Dinner2 小时前
异步Websocket构建聊天室
运维·网络·websocket·网络协议·信息与通信
有趣的我2 小时前
wireshark介绍和使用
网络·测试工具·wireshark
Fanmeang2 小时前
OSPF高级特性之FRR
运维·网络·华为·ip·ospf·spf·frr
hashiqimiya3 小时前
配置tcp的https协议证书
网络·tcp/ip·https