摘要
- IETF 于 2026 年 8 月在 Standards Track 发布 RFC 10036,注册 Boolean 类型的 HTTP
Incremental字段。?1请求理解该字段的中间层在一条消息的正文到达时逐步向下游转发;它不是端到端模式锁,也不能约束不认识该字段的设备。 - 支持该机制的中间层应先转发完整 header section,再持续放行正文,而不是等待消息结束;它仍可完整缓存 header、trailer,以及按时间或字节数受限的少量正文。若它理解请求却决定彻底拒绝,就必须返回错误,不能以成功外观偷偷改成整段缓存。
设想一条安全告警流:源站在连接建立后一秒写出第一条告警,随后每秒一条。边缘代理立即转发,下一层安全网关却要求看完全部响应才能检查内容。响应设计为持续八小时,网关便等待八小时。源站的写调用成功,连接没有断,客户端也没有收到网络错误,但第一条告警已经失去意义。
这里没有任何一条局部记录必然错误。错误发生在解释层:团队把“发送者请求增量转发”当成了“所有节点已经按时交付”。
RFC 10036 正是为这条缝隙提供共同语言。RFC 9110 的 HTTP Semantics允许接收者在消息逐段到达时处理,也允许中间层为了效率、安全、访问控制或转换而延迟、缓存。对于普通有限响应,这常是合理实现;对于必须在结束前产生价值的应用,整段缓存可能令协议语义仍然正确、产品却完全失效。
Server-Sent Events 是最清楚的单向案例:响应不结束,事件才得以持续出现,等待完整响应就可能永不放行。Chunked Oblivious HTTP Messages 草案则展示双向问题:客户端尚在发送请求时,服务器可能已经需要响应;任何一侧的整段缓存,都可能让另一侧等不到继续工作的条件。该文件仍是 work in progress,不能当成最终标准或部署证明。
RFC 10036 没有宣布所有 HTTP 都是流。它只把“这条消息需要在结束前向前走”编码出来,并规定认识这项请求的实现如何回应。
一个 Boolean,四种不同证据状态
Incremental 使用 Structured Field Values for HTTP 的 Item 类型,而且只接受 Boolean。
Incremental: ?1 请求逐步转发;Incremental: ?0 保留 HTTP 默认选择,中间层仍可以等到消息完整后再向下游发送,显式的 false 甚至可能让它更有把握选择缓存。字段不存在时,发送者没有通过 RFC 10036 提出请求。字段若采用其他 Structured Field 类型,接收者会忽略它。
这四种状态不能压缩成监控面板上的一个“streaming”开关。?1 是意图,不是逐跳确认;?0 没有命令对方必须缓存;缺席不是拒绝;错误类型被忽略,也不等同于协商失败。要判断结果,必须知道每一层是否识别、解析成什么、选择了哪条执行路径。
IANA HTTP Field Name Registry 已把 Incremental 列为 permanent,Structured Type 为 Item,引用 RFC 10036。注册表保护名称和语法不被随意复用,却不会安装实现,不会穿透 WAF,更不会量出首字节。
方向属于每条消息,不属于整个会话
一条长请求可以边上传边处理,服务器也可以在请求尚未结束时开始响应。如果应用要求两个方向都逐步推进,请求与响应必须各自携带 Incremental: ?1。请求中的 true 不会自动继承给响应;响应上补一个字段,也救不回前一跳已经整段扣留的请求正文。
这项分离直接决定如何取证。请求和响应可能经过不同的适配器、检查策略与连接池,承受不同的 backpressure。重试可能换到另一处 edge。只记录“这次 trace 开启 streaming”,会抹掉哪一条消息、哪一个 attempt、哪一个方向被谁缓存。
支持 RFC 10036 的中间层收到 ?1 后,不应等待整条消息。它应把完整的 header section 发给下游,随后持续转发到达的正文。字段只约束 message content,所以 header section 与 trailer section 仍可完整收齐后再送出。规范没有把应用的一次 write、HTTP frame、网络 packet 和客户端的一次 read 强行变成一一对应。
同一请求也到达 HTTP API 与应用框架。多数 API 能提供逐步读写;若某个接口会引入缓存,它应利用字段来减少或关闭缓存。但本地 streaming reader 只证明本地能力。它不能替上游 CDN 作证,也不能说明下游业务代码何时拼出第一条可用事件。
已理解的拒绝必须显形
RFC 10036 最有治理价值的部分,不是 ?1 本身,而是对“明知请求却静默违背”的限制。中间层若理解字段并决定完全不做增量转发,就必须生成 error response;它不能先接受,再把全文存完,最后以普通成功方式转交。
这把三种主体分开:旧实现可能不知道字段,因而按既有行为缓存;支持者可以执行请求;知情但不兼容者可以明确拒绝。规范没有把未采用定性为违规,但不允许已经采用语义的实现用成功外观隐藏相反行为。
完整正文安全检查是典型的永久冲突。如果网关只有看到最后一个字节才能判断内容是否安全,它就无法同时在判断之前把内容发出去。RFC 10036 建议返回 501 Not Implemented,并在 Proxy-Status 使用 incremental_refused。
IANA HTTP Proxy-Status 注册表把 incremental_refused 关联到推荐状态 501,并标明它只能由中间层生成。它说明的是路径中的兼容性决定,不代表源站拒绝业务请求,也不证明最终用户看见了完整诊断。
容量拒绝属于另一类。长期增量连接会持续占用连接、请求槽、内存和调度资源。中间层可以为它设置比普通流量更严格的并发上限,以保护其他请求。到达上限时,RFC 10036 建议使用 RFC 6585 定义的 429 Too Many Requests,并附 connection_limit_reached。安全上永远不兼容与容量上暂时不能接纳,需要不同告警、不同回退和不同重试预算。
少量缓存仍然属于增量转发
立即冲刷每一个微小片段会增加 packet、系统唤醒与调度成本,也可能让攻击者用大量小写入消耗中间层。RFC 10036 因此允许少量缓存:实现可以等到达到字节阈值或时间阈值再放行。
关键约束是不能无限期持有。到达任一阈值,数据需要继续前进。运营团队也必须承认取舍:更大的 batch 能提高效率,却会增加应用延迟;更小的 batch 能缩短等待,却可能降低整体容量。
因此,“收到首字节”不是完整 SLO。某层可以迅速放出第一小段,随后把后续内容攒十秒;客户端也可以持续收到不能组成完整事件的碎片。一条响应最终 2xx 并完整结束,仍可能错过所有实时价值。
需要分别记录 header 完成、首个正文 byte、后续进度、最长 inter-byte gap、首个完整可用事件、trailer 与消息完成。还要标明观测位置。源站写入时间、代理发出时间与客户端消费时间描述不同事实,不能用一个平均 latency 互相代替。
Proxy-Status 是证词,不是抓包
RFC 9209 允许中间层在 Proxy-Status 说明响应处理。成员顺序从靠近源站的一层排到靠近 user agent 的一层,可携带 error、next hop、received status 等信息;如果流已经开始后才发生问题,有些信息可能只能写进 trailer。
这种可见性有意保持边界。中间层自己决定何时发送字段,可以为了保护内部拓扑而删减内容,参数也大多可选。更重要的是,RFC 9209 明确指出内容没有被验证:一个节点可能宣称完成了某项动作,实际执行却不是如此。
所以,看到 incremental_refused 是一条具体的拒绝证据;没有看到,绝不是支持证明。未知字段的旧节点不会报告,新节点可能按策略不披露,trailer 也可能在下游丢失。最终结论必须把字段与 parser 结果、策略版本、buffer 阈值、入口字节、出口字节及客户端观测对齐。
Header 不能替团队选择传输架构
请求和响应都带 ?1 时,RFC 10036 可以帮助形成双向 byte channel,也能让早期响应在请求未结束时前进。但规范随即指出:对于真正的双向协议,HTTP/2 Extended CONNECT 与 HTTP/3 Extended CONNECT通常更符合 HTTP 架构。
逐步消费的一份表示、事件流和真正 duplex protocol 并非同一种产品契约。双向协议还需要明确的 protocol selection、双向 flow control、长期生命周期与断开语义。用两个无限长 HTTP body 模拟,可能在第一版容易上线,却把 SDK、中间层例外和客户集成锁在难以逆转的路径。
先验配置或针对单个 resource 的 probe,可以证明某条具体路径在当时支持。它不能生成永久全局能力:路由会变、检查规则会变、版本与负载也会变。RFC 10036 errata 查询在 2026 年 8 月 30 日显示没有匹配记录;这只是当天的注册表事实,不代表以后永远不会出现报告。
为每次放行建立证据链
一份可辩护记录应保留 resource、方向、request ID、trace、attempt、HTTP version、逐跳 connection 与 route;每个入口和出口的字段原值;解析结果;支持和安全策略版本;容量 admission;时间与字节冲刷阈值;header、正文接收与发送时间;最长间隔;首个可用事件;trailer、完成、取消、reset、status、Proxy-Status,以及不带字段或显式 ?0 的对照请求。
测试形态不能只有快速大块数据。还要覆盖一次一字节、慢速周期事件、burst、backpressure、永不结束的 body、必须完整检查的安全规则、并发耗尽、取消、重试和路径切换。只在一条已知实验路径上成功,不足以证明生产属性。
Heng Lu 的运行代码优先把权威放在这条实际执行链,而非文档、注册或配置项。他关于最小初始规范、本地化未来决策与自愿采用的设计说明了 RFC 10036 的克制:共同层只携带必要意图,安全、容量与架构仍由运行实现本地决定。他对技术能力与实际控制的区分进一步说明:发送者在技术上可以正确表达请求,却没有实际控制独立中间层的放行机关。
Incremental 让问题可以穿过网络。只有逐跳字节记录,才能让答案成立。
会员简报
档案背景详情
使用相应会员等级登录,即可解锁完整简报与来源注释。
仅限 Strategic Circle
Strategic Circle
所有读者均可浏览。加入并登录后可解锁档案简报。
加入 Strategic Circle仅限 Leadership Alliance
Leadership Alliance
符合条件的 IP 资产所有者和管理层可登录查看 Leadership Alliance 简报。
加入 Leadership Alliance
