HTTP 响应头
HTTP 响应头是对浏览器、缓存、代理、CDN 和前端运行环境发出的"行为说明书",按消费者和控制目标分为 9 大类。
#type / concept
#status / evergreen
#tech / network
#resource / http
#protocol / http
[!info] related notes
- 所属 MOC: http-and-frontend-networking-moc
- 上位主题: http
- 内容描述头: http-content-description-headers
- 缓存体系: 浏览器缓存体系
- CORS: cross-origin, cross-origin-and-cors-interview-question
- Cookie: cookie-session-token, HttpOnly Cookie, SameSite
- 安全头: CSP, HSTS, x-content-type-options, x-frame-options, referrer-policy, permissions-policy, cross-origin-isolation-coop-coep
- 下载与范围: large-file-download-range-request
- 限流: rate-limiting-headers
- 代理与调试: proxy-cdn-debug-headers
HTTP 响应头
一句话定义
HTTP 响应头不是业务数据本身,而是后端对浏览器、缓存、代理、CDN 和前端运行环境发出的”行为说明书”——控制缓存、安全、跨域、认证、下载、重定向等行为的元信息和控制指令。
核心模型:响应头由谁消费
一次 HTTP 响应从后端到前端代码,可能经过多层消费者,每一层只关心自己领域的头:
后端应用
↓
反向代理 / 网关 / CDN ← Via, Age, Server, X-Cache, CF-Cache-Status
↓
浏览器网络层 ← Content-Encoding, Transfer-Encoding, Content-Length
↓
浏览器缓存 ← Cache-Control, ETag, Last-Modified, Expires, Vary, Age
↓
安全策略引擎 ← CSP, HSTS, X-Frame-Options, X-Content-Type-Options,
Referrer-Policy, Permissions-Policy, COOP/COEP/CORP
↓
渲染引擎 / JS Fetch / XHR ← CORS 头 (Access-Control-*), Set-Cookie
↓
前端代码 ← Content-Type, Content-Disposition, X-Request-Id,
X-Total-Count, RateLimit-*
关键认知:请求可能已经到达服务器、服务器也已经返回了,但浏览器可能不把结果交给 JS(CORS 拦截)。响应头的消费者不只是”前端代码”,而是整条链路上的每一层。
9 大类速查
| 类别 | 典型响应头 | 解决什么问题 |
|---|---|---|
| 内容描述 | Content-Type, Content-Length, Content-Encoding, Content-Disposition | 这是什么内容?怎么解码?多大?下载还是预览? |
| 缓存 | Cache-Control, ETag, Last-Modified, Expires, Vary, Age | 能不能缓存?缓存多久?怎么验证? |
| Cookie / 会话 | Set-Cookie | 登录态、会话、追踪标识 |
| 跨域 CORS | Access-Control-* | 浏览器是否允许前端 JS 跨源读取响应 |
| 安全 | CSP, HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy, COOP/COEP/CORP | 防 XSS、点击劫持、HTTPS 降级、MIME 嗅探等 |
| 重定向 / 路由 | Location, Retry-After | 跳到哪里?多久后再试? |
| 下载 / 范围请求 | Content-Disposition, Accept-Ranges, Content-Range | 文件下载、断点续传、视频拖动 |
| 认证 / API 控制 | WWW-Authenticate, Allow, Link, RateLimit-* | 鉴权、方法约束、分页、限流 |
| 代理 / CDN / 调试 | Via, Age, Server, X-Request-Id, Traceparent | 经过了谁?缓存多久?如何排查链路? |
排查框架
遇到前端问题时,按这个顺序检查响应头:
1. 内容对不对?
Content-Type / Content-Encoding / Content-Length
2. 缓存对不对?
Cache-Control / ETag / Last-Modified / Expires / Vary / Age
3. 跨域对不对?
Access-Control-Allow-Origin / Credentials / Headers / Methods / Expose-Headers
4. 登录态对不对?
Set-Cookie / SameSite / Secure / HttpOnly / Domain / Path
5. 安全策略有没有拦?
CSP / HSTS / X-Frame-Options / Referrer-Policy / Permissions-Policy
6. 下载和媒体是否特殊?
Content-Disposition / Accept-Ranges / Content-Range
7. API 控制是否清楚?
WWW-Authenticate / Allow / Retry-After / RateLimit / Link
8. 链路能不能追?
X-Request-Id / Traceparent / Server / Via / Age / CDN 私有头
常见错误速查
| 错误 | 问题 | 正确做法 |
|---|---|---|
把 no-cache 当”不缓存” | no-cache 是”可以存,用前必须验证” | 真正不存用 no-store |
带 Cookie 的 CORS 用 * | 浏览器拒绝 | 写具体 Origin + Vary: Origin |
动态 Origin 不加 Vary: Origin | CDN 缓存了某个 Origin 的响应给另一个 Origin | 加 Vary: Origin |
| HTML 长缓存 | 用户拿到旧 HTML,引用已删除的 JS hash 文件,白屏 | HTML 用 no-cache,长缓存给 hash 静态资源 |
| JSON 的 Content-Type 写错 | text/html 返回 JSON | 用 application/json; charset=utf-8 |
| CSP 一上来太严格 | 线上资源加载失败 | 先 Report-Only 观察,再 Enforcement |
| 暴露过多服务端信息 | Server: nginx/1.20.1、X-Powered-By: Express | 简化或隐藏 |
生产环境参考模板
普通 HTTPS Web 页面
Content-Type: text/html; charset=utf-8
Cache-Control: no-cache
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
Content-Security-Policy: default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'
登录态 JSON API
Content-Type: application/json; charset=utf-8
Cache-Control: no-store
Set-Cookie: sid=xxx; Path=/; HttpOnly; Secure; SameSite=Lax
X-Content-Type-Options: nosniff
X-Request-Id: req_123
跨域带 Cookie API
Content-Type: application/json; charset=utf-8
Cache-Control: no-store
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: X-Request-Id
Vary: Origin
X-Request-Id: req_123
Hash 静态资源
Content-Type: application/javascript
Content-Encoding: br
Cache-Control: public, max-age=31536000, immutable
ETag: "abc123"
Vary: Accept-Encoding
边界与易混淆点
- 响应头不是 HTTP/2 或 HTTP/3 特有的概念:HTTP 语义由 RFC 9110 统一定义,适用于所有版本;传输格式变了,但头字段语义延续。
- 头字段名不区分大小写:
Content-Type和content-type是同一个头。 - 私有头没有标准语义:
X-Request-Id、CF-Cache-Status、X-RateLimit-Remaining等是约定俗成,不在 RFC 中。IANA 维护了 HTTP Field Name Registry。 - 前端看到的很多问题根因在响应头:跨域、缓存、登录、安全、下载问题,排查时先看响应头。