メインコンテンツまでスキップ

1. Introduction (序論)

新しいHTTPヘッダー (header) およびトレイラー (trailer) フィールドの構文を指定することは困難な作業です。[RFC7231]のセクション8.3.1のガイダンスがあっても、HTTPフィールドの作成者にとって多くの決定事項と落とし穴が存在します。

フィールドが定義されると、通常はカスタムのパーサーとシリアライザーを作成する必要があります。これは、各フィールド値が一見共通に見える構文に対してわずかに異なる処理を行うためです。

本文書は、これらの問題に対処するため、新しいHTTPフィールド値の定義で使用するための一連の共通データ構造を導入します。特に、これらのデータ構造のための汎用的な抽象モデルと、HTTP [RFC7230] ヘッダーおよびトレイラーフィールドでそのモデルを表現するための具体的なシリアライゼーションを定義します。

「構造化ヘッダー (Structured Header)」または「構造化トレイラー (Structured Trailer)」として定義されたHTTPフィールド(フィールドがどちらでもあり得る場合は「構造化フィールド (Structured Field)」)は、本仕様で定義された型を使用して構文と基本的な処理ルールを定義します。これにより、仕様作成者による定義と実装者による処理の両方が簡素化されます。

さらに、HTTPの将来のバージョンでは、これらの構造の抽象モデルの代替シリアライゼーションを定義できます。これにより、そのモデルを使用するフィールドを再定義することなく、より効率的に送信できます。

本文書の目標は既存のHTTPフィールドの構文を再定義することではありません。ここで説明されているメカニズムは、明示的にそれらを選択したフィールドでの使用のみを意図しています。

セクション2では、構造化フィールドの指定方法を説明します。

セクション3では、構造化フィールドで使用できる多数の抽象データ型を定義します。

これらの抽象型は、セクション4で説明されているアルゴリズムを使用して、HTTPフィールド値にシリアライズしたり、HTTPフィールド値からパースしたりできます。


1.1 Intentionally Strict Processing (意図的な厳格処理)

本仕様は意図的に、段階的なアルゴリズムを使用して厳格なパースとシリアライゼーションの動作を定義しています。定義されている唯一のエラー処理は、操作を完全に失敗させることです。

これは、忠実な実装と良好な相互運用性を促進するように設計されています。したがって、入力に対してより寛容であることで「役立つ」ことを試みる実装は、相互運用性を悪化させることになります。なぜなら、それは他の実装に対して類似の(しかしおそらく微妙に異なる)回避策を実装するよう圧力をかけるからです。

言い換えれば、厳格な処理は本仕様の意図的な機能です。これにより、非準拠の入力を早期に発見して修正でき、その結果生じる可能性のある相互運用性とセキュリティの問題の両方を回避できます。

この厳格性の結果として、フィールドが複数の当事者(例えば、中間者や送信者の異なるコンポーネント)によって追加される場合、一方の当事者の値のエラーにより、フィールド値全体のパースが失敗する可能性があることに注意してください。


1.2 Notational Conventions (表記規則)

本文書のキーワード「MUST (しなければならない)」、「MUST NOT (してはならない)」、「REQUIRED (必須である)」、「SHALL (しなければならない)」、「SHALL NOT (してはならない)」、「SHOULD (すべきである)」、「SHOULD NOT (すべきでない)」、「RECOMMENDED (推奨される)」、「NOT RECOMMENDED (推奨されない)」、「MAY (してもよい)」、「OPTIONAL (任意である)」は、BCP 14 [RFC2119] [RFC8174]に記載されているように解釈されるものとします。ただし、ここに示すようにすべて大文字で表記される場合に限ります。

本文書では、パースとシリアライゼーションの動作を指定するためにアルゴリズムを使用し、HTTPヘッダーフィールドの予想される構文を示すために[RFC5234]の拡張バッカス・ナウア記法 (ABNF) 表記を使用します。その際、[RFC5234]のVCHAR、SP、DIGIT、ALPHA、DQUOTEルールを使用します。また、[RFC7230]のtcharおよびOWSルールも含まれます。

HTTPフィールドからパースする場合、実装はアルゴリズムに従うことと区別できない動作を持たなければなりません (MUST)。パースアルゴリズムとABNFの間に不一致がある場合、指定されたアルゴリズムが優先されます。

HTTPフィールドへのシリアライゼーションの場合、ABNFは予想されるワイヤー表現を示し、アルゴリズムはそれらを生成するための推奨される方法を定義します。実装は、出力がセクション4.2で説明されているパースアルゴリズムによって正しく処理される限り、指定された動作から逸脱してもかまいません (MAY)。


重要なポイント (Key Takeaways)

1. 問題の背景

従来のHTTPフィールド定義の問題点:

# 各フィールドが独自の構文を持つ:
Cache-Control: max-age=3600, private
Accept: text/html, application/json;q=0.9
Content-Type: text/html; charset=utf-8
Link: `https://example.com`; rel="preload"

# 結果:
- 各フィールドにカスタムパーサーが必要
- 類似して見える構文に実際には微妙な違いがある
- エラーが発生しやすく、保守が困難

2. 解決策

構造化フィールドが提供するもの:

  • 統一されたデータ型: Integer、String、Boolean、List、Dictionaryなど
  • 標準化されたシリアライゼーション: 一貫したフォーマットルール
  • 明確なパースアルゴリズム: 曖昧さの排除
  • 将来互換性: より効率的なエンコーディングを将来使用可能

3. 厳格性の哲学

❌ 誤った例 - 寛容なパーサー:
入力: key="value (閉じ引用符がない)
寛容なパース: 引用符を自動補完、パース成功

問題:
- 異なる実装が異なる「修正」方法を持つ可能性
- 予測不可能な動作につながる
- セキュリティ脆弱性を作成

✓ 正しい例 - 厳格なパーサー:
入力: key="value (閉じ引用符がない)
厳格なパース: 即座に失敗、エラーを返す

利点:
- 生産者が正しいフォーマットを生成することを強制
- すべての実装の動作が一貫していることを保証
- 問題を早期に発見

4. 設計目標

  • 既存フィールドの再定義なし: 新しいフィールドのみに使用
  • 抽象 + 具体: 抽象モデル + HTTP/1.1シリアライゼーション
  • 将来の拡張性: HTTP/2、HTTP/3用の新しいシリアライゼーションを定義可能

5. 文書構造

セクション2: 構造化フィールドの定義方法 → 仕様作成者向けガイド
セクション3: 抽象データ型 → List、Dictionary、Itemなど
セクション4: シリアライゼーションとパースアルゴリズム → 具体的な実装詳細

実際の影響

仕様作成者への影響

従来の方法:
---------
新しいフィールド "Example-Field" を定義
- カスタムABNF構文を記述
- パースルールを詳細に説明
- 境界ケースを処理
- エラー処理を定義
(数十ページの文書が必要になる可能性)

構造化フィールド方式:
-------------
新しいフィールド "Example-Field" を定義
- RFC 8941を参照
- Dictionary型であることを説明
- キーと値の意味を定義
(数段落の文章で済む可能性)

実装者への影響

// 従来の方法 - 各フィールドにカスタムパーサーが必要
function parseCacheControl(value) {
// 50-100行のコード...
}
function parseAccept(value) {
// さらに50-100行のコード...
}
function parseContentType(value) {
// また50-100行のコード...
}

// 構造化フィールド方式 - 汎用パーサー
const cacheControl = parseDictionary(header); // 再利用
const accept = parseList(header); // 再利用
const contentType = parseItem(header); // 再利用

ネットワーク効率への影響

HTTP/1.1: テキスト形式
Example-Dict: a=1, b=2, c=3

HTTP/2 (将来): 可能なバイナリエンコーディング
[0x01] [dict] [3 items] [a:1] [b:2] [c:3]
↑ よりコンパクト、しかしロジックは同じ

適用シナリオ

✓ 構造化フィールドを使用すべき場合

  • 新しいHTTPヘッダーを定義する
  • 複雑なデータ構造 (リスト、辞書) が必要
  • 将来のより効率的なエンコーディングをサポートしたい
  • 良好な相互運用性を追求する

✗ 構造化フィールドを使用すべきでない場合

  • すでに定義されている既存フィールド (Cache-Controlなど)
  • 単純な単一値フィールド (可能だが必須ではない)
  • 古いクライアントとの下位互換性が必要なフィールド