什么是 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 请求的存在可以确保这些跨域操作在安全的前提下进行,同时让开发者能够更灵活地设计前后端分离的架构。

相关推荐
长安11082 小时前
前后端、网关、协议方面补充
网络
hzyyyyyyyu5 小时前
隧道技术-tcp封装icmp出网
网络·网络协议·tcp/ip
南猿北者6 小时前
docker Network(网络)
网络·docker·容器
Hacker_Nightrain7 小时前
网络安全CTF比赛规则
网络·安全·web安全
网络安全指导员8 小时前
恶意PDF文档分析记录
网络·安全·web安全·pdf
co0t9 小时前
计算机网络(11)和流量控制补充
服务器·网络·计算机网络
白总Server9 小时前
JVM解说
网络·jvm·物联网·安全·web安全·架构·数据库架构
清尘沐歌9 小时前
有什么好用的 WebSocket 测试工具吗?
websocket·网络协议·测试工具
清尘沐歌9 小时前
有什么好用的 WebSocket 调试工具吗?
网络·websocket·网络协议
Li_0304069 小时前
Java第十四天(实训学习整理资料(十三)Java网络编程)
java·网络·笔记·学习·计算机网络