Back

HTTP 响应中包含什么?

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 通常设置为 chunked,意味着响应体被分块发送,没有预定的总大小。在 HTTP/1.1 中,响应使用其中之一。分块编码常用于动态生成的内容,服务器事先不知道最终大小。

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

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

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

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. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay