抓包时最常见的几个字段——Cookie、Set-Cookie、X-Frame-Options——都不在那 47 个里。
它们由别的规范定义,或者干脆是事实标准。
上一节把 HTTP/1.1 的 47 个列全了。但现实里天天打交道的几个字段不在其中,这一节把它们补上。
一、Cookie 家族:RFC 6265
Set-Cookie(服务端发)和 Cookie(客户端带回来)是今天最常用的两个字段,
却不在 HTTP/1.1 的清单里——它们由 RFC 6265 单独定义。
书里为它们单开了一节(6.7),这个安排本身就说明了问题:它们是事后补进 HTTP 的,
语义上不属于报文本身,而是属于状态管理。
这也解释了为什么 Cookie 的语法特别不整齐:Set-Cookie 用分号分隔一堆属性(Path、Domain、
Max-Age、HttpOnly、SameSite),Cookie 却只传键值对。
同一个东西两个方向两种格式,是历史遗留。
二、安全类:X- 开头的那些
书里 6.8 那四个都属于这一类:
| 字段 | 作用 | 今天的状态 |
|---|---|---|
| X-Frame-Options | 禁止页面被 iframe 嵌套 | 仍广泛使用,CSP 的 frame-ancestors 是替代品 |
| X-XSS-Protection | 开关浏览器的 XSS 过滤器 | 已废弃,现代浏览器移除 |
| DNT | 请勿跟踪 | 没成为标准,几乎无人遵守 |
| P3P | 隐私偏好平台 | 已废弃 |
这四个字段放一起看很有意思:四个里三个已经死了。
它们是 2013 年前后浏览器厂商各自试水隐私保护的产物,最后只有 X-Frame-Options 活下来,
并逐渐被 CSP 取代。
DNT 的死因特别值得记:它靠「网站自愿遵守」,没有强制力。
结果是广告商不遵守,遵守的网站也没得到任何好处,最后浏览器自己把它关掉了。
三、X- 前缀到底什么意思
按早年约定,X- 表示「这不是标准字段,别指望别人也认」。
但这条约定被滥用了——大量事实上成了标准的字段也带 X-,X-Forwarded-For、X-Requested-With、
X-Frame-Options 都是。
所以 2015 年的 RFC 6648 明确建议:别再新造 X- 开头的字段了。
要么走标准化,要么就用一个你能控制的独特前缀(比如厂商名)。
现实是老的还在用,新的也还有人加。
看到 X- 开头,正确的心态是「这可能只是某家的私有约定」,而不是「这一定是非标准」。
四、几个真正的新增字段
| 字段 | 规范 | 干什么 |
|---|---|---|
Strict-Transport-Security |
RFC 6797 | 让浏览器以后只走 HTTPS |
Content-Security-Policy |
CSP | 限制能加载哪些脚本、样式、图片 |
Forwarded |
RFC 7239 | 取代 X-Forwarded-For 这一族 |
Alt-Svc |
RFC 7838 | 告诉客户端同一资源还有别的入口 |
Alt-Svc 值得单独说一句:它是 HTTP/3 能落地的关键。 |
||
| 服务器先在 HTTP/1.1 或 HTTP/2 的响应里说「我这儿也支持 HTTP/3,在某个端口上」,浏览器记住, | ||
| 下次直接试新协议。没有它,客户端根本不知道对方会不会说 QUIC。 |
五、动手 Demo:数一数这次往返里有多少个「书外」字段
先写死那 47 个字段名,再发一个带 Cookie、X-Forwarded-For、DNT 的请求, 看请求和响应里分别有几个字段不在这个集合里。
IN_47 = set(u'cache-control connection date pragma ... last-modified'.split())
print(u'请求里不在 47 个里的:')
for k in X.heads(r):
if k.lower() not in IN_47:
print(u' ' + k)
print(u'响应里不在 47 个里的:')
for k in X.heads(out):
if k.lower() not in IN_47:
print(u' ' + k)
实跑输出:
--------------------------------------------------------------------
不在那 47 个里的首部:Cookie 与安全类字段
--------------------------------------------------------------------
这次请求带出去的首部里,有哪些不在那 47 个里:
Cookie 不在 47 个里
X-Forwarded-For 不在 47 个里
DNT 不在 47 个里
响应回来的:
Set-Cookie 不在 47 个里
X-Frame-Options 不在 47 个里
Strict-Transport-Security 不在 47 个里
服务端读到的 Cookie SID=s01
几个常见的「书外」字段:
Set-Cookie RFC 6265 服务端让客户端存 Cookie
Cookie RFC 6265 客户端把 Cookie 带回来
X-Frame-Options 事实标准,后进 CSP 禁止被 iframe 嵌套
X-XSS-Protection 已废弃 早期浏览器的 XSS 过滤器开关
DNT W3C 提案,未成为标准 请勿跟踪
P3P W3C 已废弃 隐私偏好平台
X-Forwarded-For 事实标准,后由 Forwarded 取代 记客户端真实地址
Strict-Transport-Security RFC 6797 强制后续走 HTTPS
Content-Security-Policy CSP 规范 限制能加载哪些资源
Alt-Svc RFC 7838 告诉客户端「同一资源还有别的入口」
HTTP/1.1 那份 47 个的清单只是「协议自己定义的」。
现实中大量字段来自别的规范(Cookie、CSP、HSTS),
或者干脆是事实标准(X-Forwarded-For、X-Frame-Options)。
所以看到不认识的字段别慌,先查它是不是 X- 开头的自定义字段——
按约定,X- 前缀表示「不是标准字段,别指望别人也认」。
请求里有三个:Cookie、X-Forwarded-For、DNT。
响应里也有三个:Set-Cookie、X-Frame-Options、Strict-Transport-Security。
总共六个字段,都不在那 47 个里,但它们在真实流量里出现的频率,
比 Max-Forwards 或 Content-MD5 高得多。
服务端读到了 SID=s01,说明 Cookie 那个字段是正常工作 的——「不在标准清单里」不等于「不管用」。
输出最后那张表列了十个常见「书外」字段和它们的出处,能看出来源很杂:RFC 6265、RFC 6797、CSP 规范、
还有两个是「事实标准」。
30 秒实验
- 给服务端加一条
Content-Security-Policy响应首部,看它会不会被算进「书外」。 - 把
X-Forwarded-For换成Forwarded,对比两种写法的可读性。 - 想一想:为什么
DNT会失败,而Strict-Transport-Security成功了?
常见误区
- 「不在 47 个里的就是非标准字段」——很多由别的 RFC 定义,甚至是正式标准。
- 「X- 开头的一定是私有字段」——大量 X- 字段事实上成了通用约定。
- 「新字段都该加 X- 前缀」——RFC 6648 明确建议不要这么做了。
自测三问(点开对答案)
1. `Cookie` 和 `Set-Cookie` 由哪个规范定义? —— RFC 6265。它们不在 HTTP/1.1 的那 47 个字段里。 2. 书里 6.8 那四个字段里,今天还有几个活着? —— 一个半。`X-Frame-Options` 还在用,正被 CSP 取代; `X-XSS-Protection` 和 `P3P` 已废弃,`DNT` 无人遵守。 3. RFC 6648 建议了什么? —— 不要再新造 X- 开头的字段名,因为它已经无法区分「私有」和「事实标准」了。字段的清单和来源都清楚了。下一节讲一个更细的区分:哪些字段会被代理吃掉。
- ☐ (本节完,下一节 6.2.6 End-to-end首部和Hop-by-hop首部)