12k
All articles

HTTP 响应中包含什么?

HTTP 响应由状态行、响应头和响应体三部分组成,理解每个部分有助于在 DevTools 中调试并更有效地处理 fetch 请求的结果。

OpenReplay Team
OpenReplay Team
HTTP 响应中包含什么?

每次浏览器加载页面或 JavaScript 调用 fetch() 时,服务器都会返回一个 HTTP 响应。你看到的是结果——渲染的页面、一些 JSON 数据或错误消息——但响应本身包含的结构比大多数开发者有意识地思考的要多。理解这种结构能让你在 DevTools 中调试或在代码中处理响应时拥有更清晰的思维模型。

一个 HTTP 响应包含三个部分:状态行、响应头和可选的响应体。

核心要点

  • 每个 HTTP 响应由三部分组成:状态行(或 HTTP/2 和 HTTP/3 中的 :status 伪头部)、响应头和可选的响应体。
  • 状态码按其首位数字分组——2xx 表示成功,3xx 表示重定向,4xx 表示客户端错误,5xx 表示服务器错误。
  • 响应头控制缓存、安全、Cookie 和内容解析——它们告诉浏览器如何处理载荷,而不仅仅是载荷是什么
  • 在跨域请求中,并非所有响应头都能被前端 JavaScript 访问。服务器必须使用 Access-Control-Expose-Headers 来允许访问默认安全集合之外的响应头。

HTTP 响应的结构:状态、响应头、响应体

状态行

在 HTTP/1.1 中,响应以单行状态行开始:

HTTP/1.1 200 OK

这一行包含协议版本、三位数的状态码和人类可读的原因短语。原因短语仅供参考——浏览器和客户端实际上根据状态码采取行动。

HTTP 状态码按其首位数字分组:

范围含义
1xx信息性响应(请求已接收,继续处理)
2xx成功(200 OK、201 Created、204 No Content)
3xx重定向(301 Moved Permanently、304 Not Modified)
4xx客户端错误(400 Bad Request、401 Unauthorized、404 Not Found)
5xx服务器错误(500 Internal Server Error、503 Service Unavailable)

关于 HTTP/2 和 HTTP/3 的说明: 上述文本状态行是 HTTP/1.1 传输格式特有的。在 HTTP/2 和 HTTP/3 中,没有状态行。相反,状态通过 :status 伪头部传递(例如 :status: 200)。语义是相同的——状态码的含义相同——但表示形式不同。DevTools 会规范化表示形式,因此无论使用哪个协议版本,你都会看到熟悉的状态码。


HTTP 响应头:它们实际上做什么

响应头是元数据。它们告诉浏览器如何处理响应,而不是内容是什么。每个响应头都是一个不区分大小写的名称,后跟冒号和值。

以下是你最常遇到的类别:

内容元数据

  • Content-Type: application/json; charset=utf-8 — 告诉浏览器响应体的格式以及如何解码。
  • Content-Length: 1024 — 响应体的字节大小。

缓存

  • Cache-Control: max-age=3600, public — 指示浏览器和 CDN 缓存响应的时长。
  • ETag: "abc123" — 资源的指纹,用于条件请求。如果资源未更改,服务器返回 304 Not Modified 而不是完整的响应体。

安全

  • Content-Security-Policy — 限制浏览器可以从哪些来源加载脚本、样式和其他资源。
  • Strict-Transport-Security — 告诉浏览器在指定时间内仅通过 HTTPS 连接。

Cookie

  • Set-Cookie: session=xyz; HttpOnly; Secure — 指示浏览器存储 Cookie。单个响应可以包含多个 Set-Cookie 响应头,每个 Cookie 一个。

一个重要的限制:并非所有响应头都能被前端 JavaScript 访问。默认情况下,Fetch API 仅从跨域响应中公开一小部分”安全”响应头。服务器必须在 Access-Control-Expose-Headers 中明确列出额外的响应头,你的 JavaScript 才能读取它们。


响应体

响应体是实际的载荷——HTML、JSON、图像、文件。并非每个响应都有响应体。204 No Content304 Not Modified 响应会有意省略响应体。在这些情况下,状态码本身就是消息。

Content-Type 响应头告诉浏览器如何解释响应体中的内容。


值得了解的不太常见的特性

HTTP 响应还可以包含信息性响应,如 103 Early Hints,它允许服务器在主响应到达之前建议预加载资源。尾部响应头(Trailers)——在响应体之后发送的响应头——存在于 HTTP/1.1(使用分块传输编码)以及 HTTP/2 和 HTTP/3 中作为尾部响应头,但在日常前端工作中很少遇到。这些值得了解,但你不会经常在 DevTools 中看到它们。


结论

将 HTTP 响应想象成一个信封。状态码告诉你交付是否成功。响应头是外面的说明——小心处理、开封后冷藏、24 小时后过期。响应体是里面的内容。当出现问题时,首先检查状态码,然后检查响应头——它们通常会准确告诉你出了什么问题以及接下来该做什么。

常见问题

Content-Length 和 Transfer-Encoding 有什么区别?

Content-Length 指定响应体的确切字节大小。Transfer-Encoding 通常设置为 chunked,意味着响应体被分块发送,没有预定的总大小。在 HTTP/1.1 中,响应使用其中之一。分块编码常用于动态生成的内容,服务器事先不知道最终大小。

为什么我的 fetch 调用无法返回某些响应头?

对于跨域请求,Fetch API 默认只公开有限的 CORS 安全列表响应头。这些包括 Cache-Control、Content-Language、Content-Type、Expires、Last-Modified 和 Pragma。要从 JavaScript 访问任何其他响应头,服务器必须在 Access-Control-Expose-Headers 响应头中包含它。

什么时候应该使用 204 状态码而不是 200?

当服务器成功处理请求但没有响应体要返回时,使用 204 No Content。这在 DELETE 操作或表单提交中很常见,客户端不需要响应中的更新数据。当你想向客户端发送确认载荷或更新的资源时,200 OK 更合适。

如何在浏览器中检查 HTTP 响应头?

使用 F12 或 Ctrl+Shift+I 打开 DevTools,转到 Network(网络)选项卡,然后点击列表中的任何请求。Headers(响应头)面板显示请求和响应头。你还可以按请求类型筛选并搜索特定的响应头名称。Response(响应)选项卡显示服务器返回的原始响应体内容。

Open-source session replay

Gain control over your UX

See how users are using your site as if you were sitting next to them, learn and iterate faster with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.