在 localhost 上观察 HTTP 103 Early Hints —— 使用 Node.js 和 curl 确认与 200 的区别

ネットワーク・RFCカテゴリを表すパンダのイラスト 网络・RFC

关于本文
本文是通过利用生成式 AI 的自动化流程创建的。我们确认了 RFC 8297 和 Node.js 的 writeEarlyHints 规范,并构建了一个在 localhost 上区分信息响应与最终响应的实验。该实验未在目标环境中实际运行。

验证状态:📘 已查阅 RFC 及 Node.js 官方文档/未进行实机验证

HTTP 状态码并不只有 200 或 404。103 Early Hints是一种信息响应,它允许服务器在返回 HTML 等最终响应之前,向浏览器传递资源预加载的候选项。仅凭看到 103,并不能判断网站是否已正常完成响应。

我们将在 localhost 上观察这种区别。只要有 Node.js 18.11 或更高版本以及 curl,无需外部网站即可进行尝试。

HTTP 103 与 200 的作用

クライアント         サーバー
GET /       -------->
           <-------- 103 Early Hints
                     Link: </style.css>; rel=preload
           <-------- 200 OK
                     最終HTML

RFC 8297 将 103 定义为信息响应 (informational response)加载的“提示”是供客户端进行前期准备的素材。它并不能替代最终 200 或 500 的含义。

状态码主要作用是否用于判断成功
103 Early Hints提供 Link 等预先线索不可单独使用
200 OK正常的最终响应结合响应内容进行判断
404 Not Found未找到目标作为最终结果进行确认
500 Internal Server Error服务器端异常作为错误处理

尝试运行

early-hints-local.js创建一个名为该名称的文件。

const http = require("node:http");

const server = http.createServer((req, res) => {
  if (req.url === "/style.css") {
    res.writeHead(200, { "content-type": "text/css" });
    res.end("body { color: navy; }");
    return;
  }
  if (req.url !== "/") {
    res.writeHead(404);
    res.end("not found");
    return;
  }

  // 最終応答の準備が終わる前にLinkヒントを送る
  res.writeEarlyHints({
    link: "</style.css>; rel=preload; as=style"
  });
  setTimeout(() => {
    res.writeHead(200, {
      "content-type": "text/html; charset=utf-8",
      link: "</style.css>; rel=preload; as=style"
    });
    res.end("<!doctype html><h1>hello</h1>");
  }, 700);
});

server.listen(30031, "127.0.0.1", () => {
  console.log("http://127.0.0.1:30031/");
});

127.0.0.1由于仅在本地监听,因此不会对外公开。如果30031端口与其他进程冲突,请更改数字。

在终端A中启动服务器,在终端B中使用curl。

node early-hints-local.js
curl --http1.1 --include --no-progress-meter \
  http://127.0.0.1:30031/

这是预期的响应顺序(并非实际设备输出)。

HTTP/1.1 103 Early Hints
Link: </style.css>; rel=preload; as=style

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
...
<!doctype html><h1>hello</h1>

若要终止服务器,请按Ctrl+C。如果在启动Node.js时EADDRINUSE出现此提示,说明另一个程序正在占用该端口。请不要停止现有服务,而是更改示例一侧的端口。

Daily-Code-Samples:HTTP 103 本地实验已在其中放置了可执行版本和说明。

修改一处并进行观察

res.writeEarlyHints(...)注释掉该行,重新启动并执行相同的curl。这次预计103将会消失,只剩下最后的200。

// res.writeEarlyHints({
//   link: "</style.css>; rel=preload; as=style"
// });

以此确认103和200是相互独立的。此外,在localhost上res.writeHead(500)更改为…就可以复现 103 响应虽早于返回、但随后依然报错的场景。

Link 标头的意义与局限

</style.css>; rel=preload; as=style的各个部分分别指示了预加载候选的 URL、关系(preload)以及作为样式表的处理方式。然而,浏览器并不一定会进行预加载。curl 中出现了标头,也并不代表 CSS 已经被下载。

资源是否真的被更快获取,需要通过浏览器开发者工具的“网络”(Network)面板或性能测试来进行验证。如果缓存生效,前提条件也会发生变化。

实际工作中的注意事项

代理/CDN 或旧版 HTTP/1.1 客户端可能无法按预期处理信息性响应。RFC 8297 中包含了关于信息性响应互操作性的安全注意事项。

此外,在 HTTP 监控处理中,切勿将最先出现的 103 视为“响应结束”。接收到 103、最终状态码为 200、预加载确实已执行这三点需要分别进行记录。

如果在真实网站上使用,请依次确认正确的 Link 目标、实际的最终响应、客户端兼容性以及对负载的影响。除非在引入前后进行实际测量,否则切勿断言速度有所改善。

官方文档

文档信息

文章??
在 localhost 上观察 HTTP 103 Early Hints —— 使用 Node.js 和 curl 确认与 200 的区别
?布日期
更新日期
来源
https://papanda925.com/?p=18084&lang=zh

?可: ?于本站?有相??利的正文及原??表,除非?有?明,可依据 CC BY 4.0 使用。本文可能包含使用生成式AI?建或??的内容。若代??有?可声明,或?接的GitHub???定了?可,?代?以??可?准。引用内容、第三方?料、?片及商?不在本?可范?内。 使用政策

标题和URL已复制