HTTP请求头大全

请求头名称 分类 说明 示例值

请求头解析

把请求头原文粘贴进来即可逐条解析:每行一条 Name: value, 也支持浏览器开发者工具「Copy as cURL」的整段内容(会自动提取其中的 -H 参数)。 已收录的请求头会同时显示分类与说明。
收录 168 个 HTTP 请求头,覆盖内容协商、认证凭据、缓存、代理转发、CORS、Client Hints、链路追踪等 17 个分类,支持搜索、分类筛选与请求头原文解析,点击即可复制。

HTTP 请求头大全

HTTP 请求头是客户端发给服务器的「附加说明书」——它不改变请求的目标,却决定了服务器如何理解这个请求:接受什么格式、用什么身份、能不能走缓存、来自哪个 IP、经过哪条链路。这个工具收录了 168 个常用请求头,按 17 个分类整理,并附带一个请求头原文解析器。

怎么用

  1. 在搜索框输入关键词(如 Accept、缓存、X-Forwarded、追踪),列表实时筛选;
  2. 点分类标签可只看某一类,如「代理与转发」「Client Hints」;
  3. 点击请求头名称*复制名称,点击*示例值复制示例;
  4. 下方「请求头解析」面板可以粘贴整段请求头(每行一条 Name: value),自动逐条解析并标注是否已收录;
  5. 从浏览器开发者工具「Copy as cURL」复制的内容也能直接粘贴——会自动提取其中的 -H 参数。

分类速览

分类内容举例数量
内容协商Accept、Accept-Encoding7
内容主体Content-Type、Content-Length11
认证与凭据Authorization、Cookie11
缓存与条件请求Cache-Control、If-None-Match8
范围请求Range、If-Range3
连接与传输Connection、Transfer-Encoding11
代理与转发X-Forwarded-For、X-Real-IP17
客户端信息User-Agent、Referer、Origin10
Fetch 元数据Sec-Fetch-Site、Sec-Fetch-Mode6
CORS 预检Access-Control-Request-Method3
Client HintsSec-CH-UA、Sec-CH-DPR19
网络状况Downlink、ECT、RTT6
链路追踪traceparent、X-Request-ID20
WebSocketSec-WebSocket-Key5
云服务与签名X-Amz-Date、X-Goog-Api-Key10
自定义扩展X-Idempotency-Key、Prefer14
已废弃Warning、P3P、X-UIDH7

请求头的结构:为什么冒号不能省

一个请求头由三部分组成:

名称: 值
  • 名称是大小写不敏感的。Content-Type、content-type、CONTENT-TYPE 在服务端看来完全等价,按惯例使用 Header-Case 只是为了可读性。
  • 值可以是单个 token、带引号的字符串、逗号分隔的列表,或带参数的结构(如 text/html;q=0.9)。
  • 名称与值之间的冒号必须是英文冒号,值前面的空格会被忽略,Name:value 与 Name: value 等价。

一个常见的坑:用中文冒号「:」或全角空格书写请求头,服务器会直接解析失败,或把整行当作无效头丢弃。

端到端头与逐跳头

RFC 9110 把请求头分成两类,这个区别直接影响反向代理的行为:

  • 端到端头(End-to-End):面向最终接收方,代理必须原样转发。绝大多数请求头属于这一类,如 Accept、Authorization、Content-Type。
  • 逐跳头(Hop-by-Hop)*:只对单次连接有效,代理*必须在转发前移除,且不得继续传递。规范定义的逐跳头只有 8 个:Connection、Keep-Alive、Proxy-Authenticate、Proxy-Authorization、TE、Trailer、Transfer-Encoding、Upgrade。

所以如果你在 Nginx 里配置 proxy_set_header Connection "",本质上就是在清理逐跳头,避免它被错误地传给上游。

关于 X-Forwarded-For:一个必须警惕的头

反向代理场景下,后端服务器看到的 REMOTE_ADDR 永远是代理的 IP。为了把真实客户端 IP 传下去,业界约定用 X-Forwarded-For 记录 IP 链路:

X-Forwarded-For: 203.0.113.195, 70.41.3.18, 150.172.238.178
                    ↑ 原始客户端      ↑ 一级代理      ↑ 二级代理

关键点在于:这个头是客户端可以随意伪造的。攻击者只要自己发一个 X-Forwarded-For: 1.2.3.4,你的日志里就会出现假 IP。

正确的取值方式是「从右往左数,跳过所有你信任的代理」:

  1. 入口代理必须无条件覆盖而非追加该头,确保最右侧始终是你自己写入的可信值;
  2. 后端取值时按「从右向左、跳过已知代理 IP 段」的顺序定位真实客户端;
  3. 只有限定了「仅接受来自自家 CDN 或负载均衡器回源」的入口,才可以信任 CF-Connecting-IP 这类由厂商覆盖写入的头。

如果直接把 X-Forwarded-For 的第一个值当作客户端 IP 用于风控或限流,等于把限流开关交给了攻击者。

Client Hints:User-Agent 的替代方案

User-Agent 是个历史包袱:格式混乱、各家随意扩展、既暴露隐私又难以解析。浏览器厂商的应对是 UA 缩减(UA Reduction),把 UA 字符串冻结成固定模板:

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36

注意 Chrome/128.0.0.0——次要版本号被统一填成 0.0.0,真实版本不再暴露。

替代方案是 Client Hints,一套以 Sec-CH- 开头的请求头,按「熵」分级:

  • 低熵(默认发送):Sec-CH-UA、Sec-CH-UA-Mobile、Sec-CH-UA-Platform,足够做基础的浏览器与平台识别;
  • 高熵*(需服务器显式申请):Sec-CH-UA-Platform-Version、Sec-CH-UA-Arch、Sec-CH-UA-Model、Sec-CH-UA-Full-Version-List 等。服务器必须在响应中返回 Accept-CH 列出需要哪些提示,浏览器才会在*后续请求中发送。

这种「按需申请」的机制,把「是否暴露指纹」的决定权交还给了服务器与用户代理之间的协商,而不是让每个请求都带上完整指纹。

Sec-Fetch-*:浏览器提供的可信信号

传统上服务端判断「这个请求是不是跨站伪造」只能依赖 Origin 和 Referer,而这两个头都可能缺失或被策略裁剪。

Sec-Fetch-* 系列由浏览器强制写入,页面脚本无法伪造,这是它最有价值的地方:

请求头作用
Sec-Fetch-Site发起方与目标的关系:same-origin / same-site / cross-site / none
Sec-Fetch-Mode请求模式:cors / no-cors / navigate / same-origin
Sec-Fetch-Dest资源用途:document / script / image / empty
Sec-Fetch-User是否由用户激活(点击)触发

一个典型的加固规则:对写操作接口要求 Sec-Fetch-Site 为 same-origin 或 same-site,拒绝 cross-site;同时对没有该头的请求(老浏览器、脚本客户端)单独走 Token 校验。这样既不影响正常调用,又能挡掉绝大多数浏览器发起的 CSRF。

链路追踪:让请求跨服务可追

微服务下,一个用户操作可能横跨十几个服务。追踪头的作用是把「同一次调用」串起来:

  • traceparent 是 W3C Trace Context 标准,格式为 版本-追踪ID-SpanID-标志位,跨厂商互认,是当前首选;
  • tracestate 配合它传递厂商私有状态;
  • Baggage 用来传递业务上下文(租户 ID、实验分组),让下游服务不必再查库;
  • X-Request-ID 则是最朴素的方案:一个请求一个 ID,贯穿日志即可用检索串起全链路。

实践中两者常常并存——X-Request-ID 给运维看日志,traceparent 给 APM 画调用树。

常见坑

  • Content-Length 与 Transfer-Encoding: chunked 同时出现:不同实现取值不同,是「HTTP 请求走私」的经典入口,二者必须互斥。
  • 大小写不一致导致取不到值:虽然规范说名称大小写不敏感,但自己写的解析代码若用 headers['Content-Type'] 硬匹配,遇到 content-type 就会取空,解析前应统一转小写。
  • Referer 的拼写:标准里就是 Referer(少一个 r),这是 RFC 沿用的历史笔误,写 Referrer 服务器收不到。
  • 同名头重复出现:多数情况下应合并为逗号分隔列表,但 Set-Cookie 例外,它必须分行,不能合并。
  • Cookie 里的 = 和 ;:Cookie: a=b=c; d=e 中只有第一个 = 是分隔符,值里可以含 =,但含 ; 必须编码。
  • 代理链路头被无限追加:如果代理只追加不覆盖,X-Forwarded-For 会越来越长,最终触发头部大小限制返回 400 或 431。

以上请求头均可直接用于业务开发,复制后按需替换示例值即可。

常见问题 FAQ

同名请求头出现多次会怎样?

大多数情况下应合并为逗号分隔的列表,服务端按列表解析,例如多个 Accept-Encoding 会被合并处理。但 Set-Cookie 是明确的例外——它必须分行传输,不能合并,否则无法区分不同的 Cookie 属性。这是 HTTP/2 的 HPACK 压缩中唯一被特殊处理的头。

Cookie 请求头的值里能带分号和等号吗?

Cookie: a=b=c; d=e 中只有第一个等号是名称与值的分隔符,值本身可以包含等号。但分号是多个 Cookie 之间的分隔符,值里如果出现分号必须做百分号编码,否则会被解析成两个 Cookie。

traceparent 和 X-Request-ID 该用哪个?

两者目的不同,实践中常常并存。X-Request-ID 是单次请求的标识,主要用于日志串联,检索一下就能定位问题;traceparent 是 W3C 标准的分布式追踪上下文,携带父子 Span 关系,能让 APM 系统画出完整调用树。只做日志排查时 X-Request-ID 够用,要做跨服务性能分析则需要 traceparent。

请求头有大小限制吗?

有,但由服务器与代理配置决定,没有统一标准。Nginx 默认 large_client_header_buffers 为 8k,Tomcat 默认 maxHttpHeaderSize 为 8KB,Node.js 默认 maxHeaderSize 为 16KB,超限通常返回 400 或 431。这也是不应该无限追加 X-Forwarded-For 的原因之一。

OPTIONS 预检请求里为什么看不到 Authorization 头?

预检请求本身不带凭据。浏览器发预检时只发送 Origin、Access-Control-Request-Method 和 Access-Control-Request-Headers 三项信息,服务器必须用 Access-Control-Allow-Headers 明确放行 Authorization,否则实际请求根本不会发出。

自定义请求头一定要加 X- 前缀吗?

不是必须的。RFC 6648 早在 2012 年就建议不再使用 X- 前缀,因为前缀并不能真正表示「实验性」,反而造成大量事实标准长期占用该前缀。新增自定义头建议直接用有意义的业务名(如 Idempotency-Key),并做好命名空间区分。

Sec-Fetch- 系列和 Origin 有什么区别?

两者都能反映请求来源,但可信度不同。Origin 在部分场景下会缺失(如同源 GET),也可能被某些非浏览器客户端伪造;Sec-Fetch- 系列由浏览器强制写入,页面脚本无法修改,因此更适合作为服务端的安全判断依据。建议把它作为一层信号,与 Token 校验配合使用。

Sec-CH- 开头的 Client Hints 为什么有些收不到?

因为 Client Hints 分熵级。Sec-CH-UA、Sec-CH-UA-Mobile、Sec-CH-UA-Platform 是低熵值,默认发送;平台版本、架构、设备型号、完整版本列表等属于高熵值,服务器必须先通过响应头 Accept-CH 显式申请,浏览器才会在后续请求中带上。首次请求拿不到高熵值是正常现象。

为什么我的 Referer 头收不到?

先检查拼写——标准里就是 Referer,少一个 r,这是 RFC 沿用的历史笔误,写成 Referrer 服务器不会识别。其次检查页面是否设置了 Referrer-Policy: no-referrer,或从 HTTPS 页面跳转到 HTTP 时被浏览器裁剪掉了。

Content-Length 和 Transfer-Encoding 可以同时存在吗?

不可以。两者同时出现时不同实现的处理方式不一致,是 HTTP 请求走私(Request Smuggling)的经典入口。规范要求二者互斥:已知长度用 Content-Length,长度未知用 Transfer-Encoding: chunked。

X-Forwarded-For 能直接用来做限流或风控吗?

不能直接信任。这个头客户端可以随意伪造,攻击者发一个 X-Forwarded-For: 1.2.3.4 就能伪装 IP。正确做法是:入口代理无条件覆盖该头,后端取值时从右往左跳过已知的可信代理 IP,并限定只接受来自自家 CDN 或负载均衡器回源的请求。

请求头名称大小写有区别吗?

没有。按 RFC 9110,字段名是大小写不敏感的,Content-Type 与 content-type 完全等价。惯例上使用 Header-Case 只是为了可读。但要注意:自己写解析代码时如果直接按字符串硬匹配,大小写不一致就会取不到值,解析前应统一转成小写。