要約

  • 2026 年 8 月に IETF Standards Track として公開された RFC 10036 は、Boolean の HTTP field Incremental を登録した。?1 は、その field を扱う中間装置に対し、一つのメッセージの content を到着に合わせて転送するよう求める。未知の中間装置を拘束する end-to-end の mode bit ではない。
  • 対応する中間装置は header section を送り、その後に content byte を継続して解放すべきである。ただし header、trailer、時間または byte 数で限定された少量の content は buffer できる。意味を理解した上で完全に拒否するなら、メッセージ全体を黙って貯める代わりに error response を返さなければならない。

監視用イベントを一秒ごとに生成する origin を考える。最初の reverse proxy はすぐ転送する。次の security gateway は body 全体を検査するまで下流へ出さない。応答は一日中続く設計なので、gateway は一日中待てる。origin の write は成功し、TCP connection は生き、client に reset も届かない。にもかかわらず、監視画面は空のままである。

「送った」「つながった」「受け取った」は別の命題である。Incremental が記録するのは最初の意図であって、最後の結果ではない。

RFC 10036 は、RFC 9110 の HTTP Semantics が許している二つの実装を区別するために生まれた。受信者は到着した部分から処理できる一方、中間装置は効率、可用性、access control、content inspection、変換のために転送を遅らせたり、全体を buffer したりできる。有限で短い body では便利でも、完了前の進捗を前提とするアプリケーションでは機能停止になる。

Server-Sent Events は一方向の典型である。通知を送り続けるために response は開いたままになり、全体完了を待つ proxy は何も出せない。RFC 10036 が informative reference として挙げる Chunked Oblivious HTTP Messages の draft では、client が request を送り終える前に server が応答し得る。片方を全体 buffer すれば、両側の進捗が互いを待つ。ただし後者は Internet-Draft であり、完成した標準や普及状況を示す資料ではない。

RFC 10036 の役割は、buffer をなくすことではない。完全受信前の転送が必要だという意思を共通形式にし、理解した装置の応答を規律化することである。

同じ field に見える四つの状態

IncrementalStructured Field Values for HTTP の Item であり、有効なのは Boolean だけである。

Incremental: ?1 は逐次転送を求める。Incremental: ?0 は、全体を buffer する可能性を含む HTTP の default behavior を維持し、明示された false がその選択への確信を高めることもある。field がなければ RFC 10036 に基づく要求はない。別の型なら受信者は field を無視する。

したがって、?1 を「streaming 成功」、?0 を「buffer 指示」、欠落を「拒否」、型違反を「非対応」と置き換えてはならない。どれも受信実装への入力であり、その実装が field を知っているか、どう parse したか、どの policy branch を選んだかは別に残る。

IANA HTTP Field Name RegistryIncremental を permanent、Structured Type Item として掲載し、RFC 10036 を参照する。この登録は wire vocabulary の一意性を守る。個々の CDN、gateway、resource の実装や latency を保証するものではない。

要求の単位は session ではなく message

長い request body を送りながら、server が早い response を返すアプリケーションでは、request と response の両方がそれぞれ Incremental: ?1 を持つ必要がある。request の true は response に継承されない。response が正しく field を付けても、上り方向で既に全体保存された request byte は解放されない。

この点を observability から消すと、調査が破綻する。上りと下りは異なる adapter、WAF rule、connection pool を通ることがある。retry で edge が変わることもある。一つの trace に “streaming=true” とだけ記録すれば、message、方向、attempt、path の違いが見えなくなる。

対応中間装置は ?1 を含む header section を受けると、message 全体を待つべきではない。header section を下流へ送り、content byte を到着に合わせて継続的に転送すべきである。ただし field の対象は message content であるため、header section 全体と trailer section 全体の buffer は許される。application の一回の write が一つの frame、packet、client read になるという約束もない。

要求は HTTP implementation と API にも届く。incremental transfer を提供できる API が内部で余分に buffer するなら、field を使って量を減らすか無効にすべきである。しかし local API が stream reader を返す事実は、上流 WAF の放出時刻を証明しない。byte が届いても、application が一つの有効なイベントに組み立てるまで時間がかかる場合もある。

理解した拒否は通常成功に隠せない

RFC 10036 の重要な境界は、未知と意図的拒否の間にある。field を知らない中間装置は、未知の field を無視して従来どおり buffer し得る。対応装置は要求を実行できる。field を理解する装置が完全に拒否することもできる。ただしその場合、error response を生成しなければならず、全体を保存して後から普通に転送する選択はできない。

採用していないことを違反にする規則ではない。採用した意味を知りながら、その反対を成功として見せる曖昧さを除く規則である。

恒久的な拒否の例は full-content security inspection だ。最後の byte まで見なければ安全性を判断できない gateway は、判断前に同じ content を下流へ出せない。RFC 10036 は 501 Not Implemented と Proxy-Statusincremental_refused を推奨する。

IANA HTTP Proxy-Status registry では、incremental_refused の推奨 status は 501 で、intermediary のみが生成する response とされる。これは origin の業務処理が拒否した証拠ではなく、経路上の一つの互換性判断を示す。

一時的な capacity 拒否は別である。長時間の incremental request は connection、request slot、memory、scheduler を占有する。通常 traffic を守るため、incremental traffic に厳しい concurrency limit を設けてもよい。限界時に RFC 10036 が推奨するのは、RFC 6585 の 429 Too Many Requests と connection_limit_reached である。安全上の非互換と一時的な枯渇を同じ retry policy に入れてはいけない。

小さな buffer は残る

一 byte ごとに即座に flush すれば、packet、wake-up、scheduling の overhead が増える。攻撃者が大量の小さな write で中間装置に仕事を強制することもできる。そのため RFC 10036 は、時間または byte 数の threshold による少量の buffering を認める。

無期限であってはならない。どちらかの threshold に達したら data は前へ進む必要がある。運用上は二つの予算を一緒に見る。batch を大きくすれば効率は上がり得るが、利用可能になる時刻は遅れる。小さくすれば反応は速いが、capacity を削る場合がある。

time to first byte だけでは不十分である。最初の fragment を早く出し、その後を十秒ずつ貯める実装もできる。client が byte を受け続けても、一つの application event が完成しないこともある。最終 status が成功し、message が完全に終わっても、リアルタイムの契約は破られ得る。

header 完了、最初の content byte、以後の進捗、最大 inter-byte gap、最初の useful event、trailer、message 完了を別々に記録する。さらに origin write、proxy receive/send、client consume の観測点を明記する。一つの平均値で統合すると、buffer の所有者が見えなくなる。

Proxy-Status は有力な証言だが検証済み事実ではない

RFC 9209Proxy-Status は、中間装置が response と関連 request の処理を説明する仕組みである。member は origin 側から user agent 側の順に並び、error、next hop、received status などを示せる。streaming 開始後に起きた障害は trailer にしか追加できないこともある。

しかし公開は optional である。内部 topology を守るため詳細を削り、debug 時だけ field を出す運用もできる。多くの parameter も optional である。さらに RFC 9209 は field 内容が verified ではないと明記する。装置は実際とは異なる action を主張し得る。

従って incremental_refused があれば、明示的拒否の強い手掛かりになる。なければ対応の証明にはならない。旧装置は error type を知らず、policy が field を消し、trailer が下流で失われる場合がある。parse result、policy version、threshold、入口と出口の byte、client 観測との照合が必要である。

field は transport architecture を選ばない

request と response の両方に ?1 があれば、早い response を含む bidirectional byte channel を作りやすくなる。それでも RFC 10036 は、双方向 protocol には HTTP/2 の Extended CONNECTHTTP/3 の Extended CONNECT が一般に HTTP architecture と整合しやすいと述べる。

段階的に読む representation、event feed、本当の duplex protocol は同じものではない。duplex には protocol selection、双方向 flow control、長い lifecycle、切断処理が必要になる。二本の長大な message body で代用すると、初期実装は簡単でも、SDK、middlebox exception、顧客契約がその形に lock-in される。

prior knowledge や resource 単位の probe は、特定 path の現時点の support を示せる。route、security rule、version、load は変わるので、永続的な global capability にはならない。RFC 10036 の errata 検索は 2026 年 8 月 30 日時点で一致する報告を返さなかった。これはその日の registry 状態であり、将来も report がないという保証ではない。

意図から useful event までを一つの記録にする

resource、方向、request ID、trace、attempt、HTTP version、各 connection と route、field の受信値と転送値、parse result、support/security policy version、capacity admission、時間と byte の flush threshold、header 完了、各境界の content receive/send、最大 gap、最初の useful event、trailer、完了、cancel、reset、status、Proxy-Status、field なしまたは ?0 の control を保存する。

一 byte ずつ、低速 event、burst、backpressure、終わらない body、全体検査 rule、concurrency exhaustion、cancel、retry、path change を試す。高速な一つの test resource だけで成功しても、RFC が解決しようとした条件を再現していない。

Heng Lu の Running-Code Primacy に従えば、権限は field の出版ではなく、この実行結果にある。Minimum Initial Specification、Localized Future Decision、Voluntary Adoption は、一つの共通信号だけを標準化し、security、capacity、architecture の判断を running implementation に残す設計を説明する。technical capability と practical control の区別 も同じ境界を示す。sender は要求を技術的に表現できるが、独立した buffer を実際に操作する権限までは持たない。

RFC 10036 は要求を明確にする。実際に流れた byte だけが、応答を明確にする。