Summary

  • RFC 6265规定了往返路线:服务器用 Set-Cookie 交给浏览器名称和值;适用的后续请求再用 Cookie 带回。规范要求服务器尽量少发、少占字节。
  • RFC 6585在 2012 年 4 月引入 431,用于整组请求头过大或单个字段过大。缩小后可以重试,431 响应不得缓存。
  • HTTP/2与 HTTP/3仍允许服务器拒绝超出自身处理限额的字段块或请求头段。传输压缩没有取消接收端的限额。

包裹原路退回

顾客第二次打开一家网店。浏览器请求首页,同时带上一串 Cookie:登录会话、偏好设置、几个实验标记。它们多数来自网站此前的指令。请求抵达入口代理或服务器时,头部总量超过该处愿意处理的上限。于是回来的不是首页,而是 431。发出这些状态的店铺,拒收装着状态的包裹。

这条路径写在 2011 年 4 月发布的 RFC 6265里。服务器可在响应中发 Set-Cookie,浏览器依据域名、路径等条件保存并回送名称和值。有效期、作用范围等属性决定何时回送,却不作为 Cookie 名值对原样返回。一次下发动作可以变成后续许多次请求的固定负担。

规范第 6.1 节给出一组容易被误读的数字:通用浏览器应至少支持单个 Cookie 4096 字节、每个域名 50 个 Cookie。紧接着它要求服务器尽量少用、缩小 Cookie,因为 Cookie 会随每次适用请求发送。前两个数字是浏览器的最低存储能力,不是所有网关和服务器对整段请求头的共同接收承诺。一端记得住,另一端未必肯读完。

431 给堵塞编号

2012 年 4 月,RFC 6585为 HTTP 增添四个状态码。其中 431 的全称是 Request Header Fields Too Large。全部字段相加过大,或某一个字段独自过大,都可触发它。若问题集中在单个字段,响应内容应指出那个字段。请求头缩小后可再次提交。规范还禁止缓存 431 响应,避免把针对这次大包裹的拒收当成以后请求的固定答案。

编号解释了拒收,却没有规定全网统一的字节上限,也没有替浏览器挑选要删掉的 Cookie。更棘手的是,RFC 6585 允许服务器在遭受攻击时直接断开连接,而不必一定发送 431。用户看到的可能只是打不开的页面。要知道究竟是边缘网关、代理还是源站拒收,得看被拒那一跳的记录,而不是猜测浏览器出了故障。

清空全部 Cookie 确实可能让请求变小,也会丢掉登录状态和偏好。如果网站随后重新下发同样多的值,问题又会回来。一个真正可用的修复入口必须允许较小的请求抵达;否则帮助页面也被关在同一道门后面。服务器发了多少状态、持续多久、覆盖哪些路径,只有运营方掌握完整账本。

线上的包变小,门框没有变宽

新版本 HTTP 对头部做了更有效的传输处理,接收端仍有权设限。2022 年的 RFC 9113写明,HTTP/2 服务器面对超出自身处理意愿的字段块,可以返回 431。RFC 9114对 HTTP/3 的请求头段作了相同安排。压缩改变线上运送的字节数;接收端仍须处理展开后的字段集合。

因此事故现场可能出现两张互相顶嘴的图:网络侧显示传输很轻,应用入口却看到解码后的头部太重。431 也不能自动告诉工程师是一个巨大的 Cookie 字段,还是许多普通字段相加造成的。授权凭据等其他字段同样占用额度。四份原始 RFC 没有给出 Cookie 引发 431 的真实事故数量;判断具体故障,需要抓到请求并找出第一个拒收组件。

这段协议史的笑点落在责任归属上。浏览器忠实搬运,入口执行自己的配额,应用可能连请求都没见到。能从源头减少负重的,是决定下发哪些值、让它们活多久、到哪些路径都要携带的网站。431 只是门卫写在退件条上的数字。谁让包裹变小,仍由运营者决定。