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

3. メッセージ形式

すべての HTTP/1.1 メッセージは、インターネットメッセージ形式 [RFC5322] に類似した形式のオクテット列が続く開始行で構成されます: 0 個以上のヘッダーフィールド (まとめて "headers" または "header section" と呼ばれます)、ヘッダーセクションの終わりを示す空行、および任意のメッセージ本文です。

HTTP-message   = start-line
*( header-field CRLF )
CRLF
[ message-body ]

HTTP メッセージを解析する通常の手順は、開始行を構造体に読み込み、空行に達するまで各ヘッダーフィールドをフィールド名でハッシュテーブルに読み込み、次に解析済みデータを用いてメッセージ本文が期待されるかどうかを判断することです。メッセージ本文が示されている場合、メッセージ本文長に等しい量のオクテットが読み込まれるか、接続が閉じられるまで、ストリームとして読み込まれます。

受信者は、US-ASCII [USASCII] のスーパーセットであるエンコーディングのオクテット列として HTTP メッセージを解析しなければなりません (MUST)。特定のエンコーディングを考慮せずに HTTP メッセージを Unicode 文字のストリームとして解析すると、オクテット LF (%x0A) を含む無効なマルチバイト文字列を文字列処理ライブラリが扱う方法のばらつきに起因するセキュリティ脆弱性を生み出します。文字列ベースのパーサーは、メッセージから要素が抽出された後 (例えば、メッセージ解析によって個々のフィールドが区切られた後のヘッダー field-value 内など) にのみ、プロトコル要素内で安全に使用できます。

HTTP メッセージは、増分処理または下流への転送のためにストリームとして解析できます。ただし、一部の実装はネットワーク効率、セキュリティチェック、またはペイロード変換のためにメッセージ転送をバッファリングまたは遅延させるため、受信者は部分的なメッセージの増分配信に依存できません。

送信者は、開始行と最初のヘッダーフィールドの間に空白を送信してはなりません (MUST NOT)。開始行と最初のヘッダーフィールドの間の空白を受信した受信者は、メッセージを無効として拒否するか、または空白で始まる各行をそれ以上処理せずに消費しなければなりません (MUST) (すなわち、適切に形成されたヘッダーフィールドを受信するか、ヘッダーセクションが終了するまで、空白で始まる後続の行とともに、行全体を無視します)。

リクエスト内にそのような空白が存在することは、サーバーを騙してそのフィールドを無視させたり、その後の行を新しいリクエストとして処理させたりする試みである可能性があり、そのいずれも、リクエスト連鎖内の他の実装が同じメッセージを異なって解釈する場合には、セキュリティ脆弱性をもたらす可能性があります。同様に、レスポンス内にそのような空白が存在することは、一部のクライアントでは無視されたり、他のクライアントでは解析を中止させたりする可能性があります。

3.1. 開始行​

HTTP メッセージは、クライアントからサーバーへのリクエスト、またはサーバーからクライアントへのレスポンスのいずれかです。構文的には、2 種類のメッセージは、開始行 (リクエストの場合は request-line、レスポンスの場合は status-line) と、メッセージ本文の長さを決定するアルゴリズム (セクション 3.3) のみが異なります。

理論的には、クライアントがリクエストを受信し、サーバーがレスポンスを受信することも可能で、それらは開始行の形式の違いによって区別できます。しかし実際には、サーバーはリクエストのみを期待するように実装され (レスポンスは未知または無効なリクエストメソッドとして解釈されます)、クライアントはレスポンスのみを期待するように実装されています。

start-line     = request-line / status-line

3.1.1. リクエスト行​

リクエスト行は、メソッドトークンで始まり、単一のスペース (SP)、リクエストターゲット、もう 1 つの単一のスペース (SP)、プロトコルバージョンが続き、CRLF で終わります。

request-line   = method SP request-target SP HTTP-version CRLF

メソッドトークンは、ターゲットリソースに対して実行するリクエストメソッドを示します。リクエストメソッドは大文字と小文字を区別します。

method         = token

本仕様で定義されるリクエストメソッドは、HTTP メソッドレジストリに関する情報および新しいメソッドを定義する際の考慮事項とともに、[RFC7231] のセクション 4 にあります。

リクエストターゲットは、セクション 5.3 で定義されている、リクエストを適用すべきターゲットリソースを識別します。

受信者は通常、3 つの構成要素のいずれにも空白が許可されないため、空白で分割することによってリクエスト行をその構成要素に解析します (セクション 3.5 を参照してください)。残念ながら、一部のユーザーエージェントは、ハイパーテキスト参照内に見つかった空白を適切にエンコードまたは除外できず、その結果、それらの許可されない文字がリクエストターゲット内で送信されます。

無効なリクエスト行の受信者は、400 (Bad Request) エラー、またはリクエストターゲットを適切にエンコードした 301 (Moved Permanently) リダイレクトのいずれかで応答すべきです (SHOULD)。受信者は、リダイレクトなしで自動修正してからリクエストを処理しようとすべきではありません (SHOULD NOT)。無効なリクエスト行は、リクエスト連鎖に沿ったセキュリティフィルターを回避するために意図的に細工されている可能性があるためです。

HTTP は、セクション 2.5 で説明されているように、リクエスト行の長さに事前定義された制限を設けていません。自身が実装するどのメソッドよりも長いメソッドを受信したサーバーは、501 (Not Implemented) ステータスコードで応答すべきです (SHOULD)。解析したいどの URI よりも長いリクエストターゲットを受信したサーバーは、414 (URI Too Long) ステータスコードで応答しなければなりません (MUST) ([RFC7231] のセクション 6.5.12 を参照してください)。

リクエスト行の長さに関するさまざまなアドホックな制限が実際には見られます。すべての HTTP 送信者と受信者が、少なくとも 8000 オクテットのリクエスト行長をサポートすることが RECOMMENDED です。

3.1.2. ステータス行​

レスポンスメッセージの最初の行は status-line で、プロトコルバージョン、スペース (SP)、ステータスコード、もう 1 つのスペース、ステータスコードを説明する空である可能性のあるテキスト句で構成され、CRLF で終わります。

status-line = HTTP-version SP status-code SP reason-phrase CRLF

status-code 要素は、クライアントの対応するリクエストを理解して満たそうとするサーバーの試みの結果を記述する 3 桁の整数コードです。レスポンスメッセージの残りは、そのステータスコードに対して定義されたセマンティクスに照らして解釈されます。ステータスコードのセマンティクス (最初の数字で示されるステータスコードのクラス、本仕様で定義されるステータスコード、新しいステータスコードの定義に関する考慮事項、および IANA レジストリを含む) については、[RFC7231] のセクション 6 を参照してください。

status-code    = 3DIGIT

reason-phrase 要素は、数値のステータスコードに関連付けられたテキストによる説明を提供するという唯一の目的で存在し、そのほとんどは、対話的なテキストクライアントとともにより頻繁に使用されていた初期のインターネットアプリケーションプロトコルへの敬意によるものです。クライアントは reason-phrase の内容を無視すべきです (SHOULD)。

reason-phrase  = *( HTAB / SP / VCHAR / obs-text )

3.2. ヘッダーフィールド​

各ヘッダーフィールドは、大文字と小文字を区別しないフィールド名、コロン (":")、任意の先行空白、フィールド値、および任意の後続空白で構成されます。

header-field   = field-name ":" OWS field-value OWS

field-name = token
field-value = *( field-content / obs-fold )
field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
field-vchar = VCHAR / obs-text

obs-fold = CRLF 1*( SP / HTAB )
; obsolete line folding
; see Section 3.2.4

field-name トークンは、対応する field-value がそのヘッダーフィールドによって定義されたセマンティクスを持つものとしてラベル付けします。たとえば、Date ヘッダーフィールドは、[RFC7231] のセクション 7.1.1.2 で、それが現れるメッセージの発信タイムスタンプを含むものとして定義されています。

3.2.1. フィールドの拡張性​

ヘッダーフィールドは完全に拡張可能です: 新しいフィールド名 (それぞれがおそらく新しいセマンティクスを定義します) の導入にも、所与のメッセージで使用されるヘッダーフィールドの数にも制限はありません。既存のフィールドは、本仕様の各部分および本ドキュメント群の外にある多くの仕様で定義されています。

新しいヘッダーフィールドは、受信者によって理解されると、以前に定義されたヘッダーフィールドの解釈を上書きまたは強化したり、リクエスト評価の事前条件を定義したり、レスポンスの意味を洗練したりするように定義できます。

プロキシは、field-name が Connection ヘッダーフィールド (セクション 6.1) に列挙されているか、プロキシがそのようなフィールドをブロックまたはその他の方法で変換するように特別に構成されていない限り、認識しないヘッダーフィールドを転送しなければなりません (MUST)。他の受信者は、認識しないヘッダーフィールドを無視すべきです (SHOULD)。これらの要件により、既に配備された仲介者を事前に更新することを要求することなく、HTTP の機能を強化できます。

定義されたすべてのヘッダーフィールドは、[RFC7231] のセクション 8.3 で説明されているように、"Message Headers" レジストリに IANA に登録されるべきです。

3.2.2. フィールドの順序​

異なるフィールド名を持つヘッダーフィールドを受信する順序は重要ではありません。ただし、実装ができるだけ早い段階でメッセージを処理しないことを決定できるように、制御データを含むヘッダーフィールド (リクエストの Host やレスポンスの Date など) を最初に送信するのが良い習慣です。後のヘッダーフィールドには、条件、認証資格情報、またはリクエスト処理に影響を与えることになる意図的に誤解を招く重複ヘッダーフィールドが含まれる可能性があるため、サーバーは、リクエストヘッダーセクション全体を受信するまで、リクエストをターゲットリソースに適用してはなりません (MUST NOT)。

送信者は、そのヘッダーフィールドのフィールド値全体がコンマ区切りリスト [すなわち #(values)] として定義されているか、そのヘッダーフィールドがよく知られた例外 (以下に記す) でない限り、同じフィールド名を持つ複数のヘッダーフィールドをメッセージ内で生成してはなりません (MUST NOT)。

受信者は、同じフィールド名を持つ複数のヘッダーフィールドを、各後続のフィールド値をコンマで区切って順番に結合済みのフィールド値に追加することによって、メッセージのセマンティクスを変えることなく、単一の "field-name: field-value" の組に結合してもかまいません (MAY)。したがって、同じフィールド名を持つヘッダーフィールドを受信する順序は、結合されたフィールド値の解釈にとって重要です。プロキシは、メッセージを転送するときにこれらのフィールド値の順序を変更してはなりません (MUST NOT)。

注: 実際には、"Set-Cookie" ヘッダーフィールド ([RFC6265]) はレスポンスメッセージ内に複数回現れることが多く、リスト構文を使用しないため、同じ名前を持つ複数のヘッダーフィールドに関する上記の要件に違反します。単一の field-value に結合できないため、受信者はヘッダーフィールドを処理する際に "Set-Cookie" を特殊なケースとして扱うべきです。(詳細については、[Kri2001] の付録 A.2.3 を参照してください。)

3.2.3. 空白​

本仕様は、線形空白 (linear whitespace) の使用を表すために 3 つのルールを使用します: OWS (optional whitespace)、RWS (required whitespace)、および BWS ("bad" whitespace) です。

OWS ルールは、0 個以上の線形空白オクテットが現れる可能性がある場合に使用されます。可読性を向上させるために任意の空白が好まれるプロトコル要素では、送信者は任意の空白を単一の SP として生成すべきです (SHOULD)。そうでない場合、送信者は、インプレースのメッセージフィルタリング中に無効または不要なプロトコル要素を空白で埋めるために必要な場合を除き、任意の空白を生成すべきではありません (SHOULD NOT)。

RWS ルールは、フィールドトークンを区切るために少なくとも 1 つの線形空白オクテットが必要な場合に使用されます。送信者は RWS を単一の SP として生成すべきです (SHOULD)。

BWS ルールは、文法が歴史的な理由のみで任意の空白を許可する場合に使用されます。送信者は、メッセージ内で BWS を生成してはなりません (MUST NOT)。受信者は、そのような不正な空白を解析し、プロトコル要素を解釈する前にそれを除去しなければなりません (MUST)。

OWS            = *( SP / HTAB )
; optional whitespace
RWS = 1*( SP / HTAB )
; required whitespace
BWS = OWS
; "bad" whitespace

3.2.4. フィールドの解析​

メッセージは、個々のヘッダーフィールド名に依存しない汎用アルゴリズムを用いて解析されます。所与のフィールド値内の内容は、メッセージ解釈の後の段階まで (通常はメッセージのヘッダーセクション全体が処理された後で) 解析されません。したがって、本仕様は、以前の版で行われていたように、各 "Field-Name: Field Value" の組を定義するために ABNF ルールを使用しません。代わりに、本仕様は、各登録済みフィールド名に従って命名された ABNF ルールを使用し、そのルールがそのフィールドの対応するフィールド値 (すなわち、汎用フィールドパーサーによってヘッダーセクションから field-value が抽出された後) の有効な文法を定義します。

ヘッダー field-name とコロンの間には空白が許可されません。過去には、そのような空白の扱いの違いが、リクエストルーティングとレスポンス処理におけるセキュリティ脆弱性につながりました。サーバーは、ヘッダー field-name とコロンの間に空白を含む受信したリクエストメッセージを、400 (Bad Request) のレスポンスコードで拒否しなければなりません (MUST)。プロキシは、メッセージを下流に転送する前に、そのような空白をレスポンスメッセージから除去しなければなりません (MUST)。

フィールド値の前および/または後に任意の空白 (OWS) が付く場合があります。人間による一貫した可読性のために、field-value の前に単一の SP を置くことが好ましいです。フィールド値には先頭または末尾の空白は含まれません: フィールド値の最初の非空白オクテットの前、またはフィールド値の最後の非空白オクテットの後に生じる OWS は、ヘッダーフィールドからフィールド値を抽出する際にパーサーによって除外されるべきです。

歴史的に、HTTP ヘッダーフィールド値は、各追加行の前に少なくとも 1 つのスペースまたは水平タブを付けることによって複数行に拡張できました (obs-fold)。本仕様は、message/http メディアタイプ (セクション 8.3.1) 内を除いて、そのような行折り返しを非推奨とします。送信者は、メッセージが message/http メディアタイプ内にパッケージングされることを意図していない限り、行折り返しを含むメッセージ (すなわち、obs-fold ルールに一致するものを含む field-value を持つメッセージ) を生成してはなりません (MUST NOT)。

message/http コンテナ内にないリクエストメッセージで obs-fold を受信したサーバーは、400 (Bad Request) を送信してメッセージを拒否するか (好ましくは、廃止された行折り返しが受け入れられないことを説明する表現を伴います)、またはフィールド値を解釈したりメッセージを下流に転送したりする前に、受信した各 obs-fold を 1 つ以上の SP オクテットに置き換えなければなりません (MUST)。

message/http コンテナ内にないレスポンスメッセージで obs-fold を受信したプロキシまたはゲートウェイは、メッセージを破棄して 502 (Bad Gateway) レスポンスに置き換えるか (好ましくは、受け入れられない行折り返しを受信したことを説明する表現を伴います)、またはフィールド値を解釈したりメッセージを下流に転送したりする前に、受信した各 obs-fold を 1 つ以上の SP オクテットに置き換えなければなりません (MUST)。

message/http コンテナ内にないレスポンスメッセージで obs-fold を受信したユーザーエージェントは、フィールド値を解釈する前に、受信した各 obs-fold を 1 つ以上の SP オクテットに置き換えなければなりません (MUST)。

歴史的に、HTTP は ISO-8859-1 文字セット [ISO-8859-1] のテキストを含むフィールド内容を許可し、他の文字セットは [RFC2047] エンコーディングの使用を通じてのみサポートしていました。実際には、ほとんどの HTTP ヘッダーフィールド値は US-ASCII 文字セット [USASCII] の部分集合のみを使用します。新しく定義されるヘッダーフィールドは、そのフィールド値を US-ASCII オクテットに限定すべきです (SHOULD)。受信者は、フィールド内容内の他のオクテット (obs-text) を不透明なデータとして扱うべきです (SHOULD)。

3.2.5. フィールドの制限​

HTTP は、セクション 2.5 で説明されているように、各ヘッダーフィールドの長さ、またはヘッダーセクション全体の長さに事前定義された制限を設けていません。個々のヘッダーフィールド長に関するさまざまなアドホックな制限が実際には見られ、しばしば特定のフィールドのセマンティクスに依存します。

処理を望むよりも大きいリクエストヘッダーフィールドまたはフィールド群を受信したサーバーは、適切な 4xx (Client Error) ステータスコードで応答しなければなりません (MUST)。そのようなヘッダーフィールドを無視すると、サーバーのリクエスト密輸攻撃 (セクション 9.5) への脆弱性が高まります。

クライアントは、フィールドのセマンティクスが、破棄された値がメッセージのフレーミングやレスポンスのセマンティクスを変えることなく安全に無視できるようなものである場合、処理を望むよりも大きい受信したヘッダーフィールドを破棄または切り詰めてもかまいません (MAY)。

3.2.6. フィールド値の構成要素​

ほとんどの HTTP ヘッダーフィールド値は、空白または特定の区切り文字で区切られた共通の構文構成要素 (token、quoted-string、および comment) を使用して定義されます。区切り文字は、トークン内で許可されない US-ASCII 可視文字 (DQUOTE および "(),/:;<=>?@[]{}") の集合から選択されます。

token          = 1*tchar

tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*"
/ "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
/ DIGIT / ALPHA
; any VCHAR, except delimiters

テキストの文字列は、二重引用符で囲まれている場合、単一の値として解析されます。

quoted-string  = DQUOTE *( qdtext / quoted-pair ) DQUOTE
qdtext = HTAB / SP /%x21 / %x23-5B / %x5D-7E / obs-text
obs-text = %x80-FF

コメントは、コメントテキストを括弧で囲むことによって、一部の HTTP ヘッダーフィールドに含めることができます。コメントは、"comment" をフィールド値の定義の一部として含むフィールドでのみ許可されます。

comment        = "(" *( ctext / quoted-pair / comment ) ")"
ctext = HTAB / SP / %x21-27 / %x2A-5B / %x5D-7E / obs-text

バックスラッシュオクテット ("") は、quoted-string および comment の構文内で単一オクテットの引用機構として使用できます。quoted-string の値を処理する受信者は、quoted-pair を、バックスラッシュに続くオクテットで置き換えられたものとして扱わなければなりません (MUST)。

quoted-pair    = "\" ( HTAB / SP / VCHAR / obs-text )

送信者は、その文字列内に現れる DQUOTE およびバックスラッシュオクテットを引用するために必要な場合を除き、quoted-string 内で quoted-pair を生成すべきではありません (SHOULD NOT)。送信者は、そのコメント内に現れる括弧 ["(" および ")"] とバックスラッシュオクテットを引用するために必要な場合を除き、コメント内で quoted-pair を生成すべきではありません (SHOULD NOT)。

3.3. メッセージ本文​

HTTP メッセージのメッセージ本文 (存在する場合) は、そのリクエストまたはレスポンスのペイロード本文を運ぶために使用されます。メッセージ本文は、セクション 3.3.1 で説明されているように転送コーディングが適用されていない限り、ペイロード本文と同一です。

message-body = *OCTET

メッセージ本文がメッセージ内で許可されるのはいつかというルールは、リクエストとレスポンスで異なります。

リクエスト内のメッセージ本文の存在は、Content-Length または Transfer-Encoding ヘッダーフィールドによって通知されます。リクエストメッセージのフレーミングは、メソッドがメッセージ本文の用途を定義していなくても、メソッドのセマンティクスから独立しています。

レスポンス内のメッセージ本文の存在は、それが応答しているリクエストメソッドと、レスポンスのステータスコード (セクション 3.1.2) の両方に依存します。HEAD リクエストメソッド ([RFC7231] のセクション 4.3.2) へのレスポンスは、メッセージ本文を決して含みません。これは、関連するレスポンスヘッダーフィールド (例えば Transfer-Encoding、Content-Length など) が存在する場合、それらが、リクエストメソッドが GET ([RFC7231] のセクション 4.3.1) であったならばどうであったかの値のみを示すためです。CONNECT リクエストメソッド ([RFC7231] のセクション 4.3.6) への 2xx (Successful) レスポンスは、メッセージ本文を持つ代わりにトンネルモードに切り替わります。すべての 1xx (Informational)、204 (No Content)、および 304 (Not Modified) レスポンスは、メッセージ本文を含みません。他のすべてのレスポンスはメッセージ本文を含みますが、本文は長さ 0 である場合があります。

3.3.1. Transfer-Encoding​

Transfer-Encoding ヘッダーフィールドは、メッセージ本文を形成するためにペイロード本文に (またはこれから) 適用される転送コーディングのシーケンスに対応する転送コーディング名を列挙します。転送コーディングはセクション 4 で定義されています。

Transfer-Encoding = 1#transfer-coding

Transfer-Encoding は、7 ビットのトランスポートサービス上でバイナリデータを安全に転送できるように設計された MIME の Content-Transfer-Encoding フィールド ([RFC2045] のセクション 6) に類似しています。しかしながら、安全な転送は、8 ビットクリーンな転送プロトコルにとっては異なる焦点を持ちます。HTTP の場合、Transfer-Encoding は主に、動的に生成されたペイロードを正確に区切り、転送効率またはセキュリティのためだけに適用されるペイロードエンコーディングを、選択されたリソースの特性であるものと区別することを意図しています。

受信者は、ペイロード本文のサイズが事前に不明なときにメッセージのフレーミングにおいて決定的な役割を果たすため、chunked 転送コーディング (セクション 4.1) を解析できなければなりません (MUST)。送信者は、chunked をメッセージ本文に 2 回を超えて適用してはなりません (MUST NOT) (すなわち、既にチャンク化されたメッセージをチャンク化することは許可されません)。chunked 以外の転送コーディングがリクエストペイロード本文に適用される場合、送信者は、メッセージが適切にフレーミングされることを保証するために、chunked を最終的な転送コーディングとして適用しなければなりません (MUST)。chunked 以外の転送コーディングがレスポンスペイロード本文に適用される場合、送信者は、chunked を最終的な転送コーディングとして適用するか、接続を閉じることによってメッセージを終端しなければなりません (MUST)。

例えば、

Transfer-Encoding: gzip, chunked

は、メッセージ本文を形成する際に、ペイロード本文が gzip コーディングを用いて圧縮され、次に chunked コーディングを用いてチャンク化されたことを示します。

Content-Encoding ([RFC7231] のセクション 3.1.2.1) とは異なり、Transfer-Encoding は表現ではなくメッセージの特性であり、リクエスト/レスポンス連鎖に沿った任意の受信者が、受信した転送コーディングをデコードしたり、メッセージ本文に追加の転送コーディングを適用したりしてもかまいません (MAY) (Transfer-Encoding のフィールド値に対応する変更が加えられることを前提とします)。エンコーディングパラメータに関する追加情報は、本仕様で定義されていない他のヘッダーフィールドによって提供される場合があります。

Transfer-Encoding は、HEAD リクエストへのレスポンス、または GET リクエストへの 304 (Not Modified) レスポンス ([RFC7232] のセクション 4.1) で送信してもかまいません (MAY)。そのいずれもメッセージ本文を含みませんが、これは、リクエストが無条件の GET であったならばオリジンサーバーがメッセージ本文に転送コーディングを適用したであろうことを示すためです。ただし、この指示は必須ではありません。レスポンス連鎖上の任意の受信者 (オリジンサーバーを含む) が、必要ないときに転送コーディングを除去できるためです。

サーバーは、ステータスコードが 1xx (Informational) または 204 (No Content) であるいかなるレスポンスでも、Transfer-Encoding ヘッダーフィールドを送信してはなりません (MUST NOT)。サーバーは、CONNECT リクエスト ([RFC7231] のセクション 4.3.6) へのいかなる 2xx (Successful) レスポンスでも、Transfer-Encoding ヘッダーフィールドを送信してはなりません (MUST NOT)。

Transfer-Encoding は HTTP/1.1 で追加されました。一般に、HTTP/1.0 のサポートのみを通知する実装は、転送エンコードされたペイロードを処理する方法を理解しないと想定されています。クライアントは、サーバーが HTTP/1.1 (またはそれ以降) のリクエストを処理することを知らない限り、Transfer-Encoding を含むリクエストを送信してはなりません (MUST NOT)。そのような知識は、特定のユーザー構成の形、または以前に受信したレスポンスのバージョンを記憶することによる場合があります。サーバーは、対応するリクエストが HTTP/1.1 (またはそれ以降) を示さない限り、Transfer-Encoding を含むレスポンスを送信してはなりません (MUST NOT)。

自身が理解しない転送コーディングを含むリクエストメッセージを受信したサーバーは、501 (Not Implemented) で応答すべきです (SHOULD)。

3.3.2. Content-Length​

メッセージが Transfer-Encoding ヘッダーフィールドを持たない場合、Content-Length ヘッダーフィールドは、潜在的なペイロード本文の想定サイズを 10 進数のオクテット数として提供できます。ペイロード本文を含むメッセージについては、Content-Length のフィールド値は、本文 (およびメッセージ) がどこで終わるかを決定するために必要なフレーミング情報を提供します。ペイロード本文を含まないメッセージについては、Content-Length は選択された表現のサイズを示します ([RFC7231] のセクション 3)。

Content-Length = 1*DIGIT

例:

Content-Length: 3495

送信者は、Transfer-Encoding ヘッダーフィールドを含むいかなるメッセージでも、Content-Length ヘッダーフィールドを送信してはなりません (MUST NOT)。

ユーザーエージェントは、Transfer-Encoding が送信されず、かつリクエストメソッドが囲まれたペイロード本文の意味を定義する場合、リクエストメッセージで Content-Length を送信すべきです (SHOULD)。たとえば、Content-Length ヘッダーフィールドは、値が 0 であっても (空のペイロード本文を示します)、通常は POST リクエストで送信されます。ユーザーエージェントは、リクエストメッセージがペイロード本文を含まず、メソッドのセマンティクスがそのような本文を想定していない場合、Content-Length ヘッダーフィールドを送信すべきではありません (SHOULD NOT)。

サーバーは、HEAD リクエスト ([RFC7231] のセクション 4.3.2) へのレスポンスで Content-Length ヘッダーフィールドを送信してもかまいません (MAY)。サーバーは、そのフィールド値が、同じリクエストが GET メソッドを使用していたならばレスポンスのペイロード本文で送信されたであろう 10 進数のオクテット数に等しくない限り、そのようなレスポンスで Content-Length を送信してはなりません (MUST NOT)。

サーバーは、条件付き GET リクエスト ([RFC7232] のセクション 4.1) への 304 (Not Modified) レスポンスで Content-Length ヘッダーフィールドを送信してもかまいません (MAY)。サーバーは、そのフィールド値が、同じリクエストへの 200 (OK) レスポンスのペイロード本文で送信されたであろう 10 進数のオクテット数に等しくない限り、そのようなレスポンスで Content-Length を送信してはなりません (MUST NOT)。

サーバーは、ステータスコードが 1xx (Informational) または 204 (No Content) であるいかなるレスポンスでも、Content-Length ヘッダーフィールドを送信してはなりません (MUST NOT)。サーバーは、CONNECT リクエスト ([RFC7231] のセクション 4.3.6) へのいかなる 2xx (Successful) レスポンスでも、Content-Length ヘッダーフィールドを送信してはなりません (MUST NOT)。

上記で定義したケースを除き、Transfer-Encoding が存在しない場合、オリジンサーバーは、ヘッダーセクション全体を送信する前にペイロード本文のサイズが既知であるとき、Content-Length ヘッダーフィールドを送信すべきです (SHOULD)。これにより、下流の受信者は転送の進捗を測定し、受信したメッセージがいつ完了するかを知り、追加のリクエストのために接続を再利用できるようになります。

0 以上の任意の Content-Length フィールド値が有効です。ペイロードの長さに事前定義された制限がないため、受信者は、潜在的に大きな 10 進数を想定し、整数変換のオーバーフローによる解析エラーを防がなければなりません (MUST) (セクション 9.3)。

同じ 10 進数値からなるフィールド値を持つ複数の Content-Length ヘッダーフィールド、または同一の 10 進数値のリストを含むフィールド値を持つ単一の Content-Length ヘッダーフィールド (例えば "Content-Length: 42, 42") を持つメッセージを受信した場合、これは、重複する Content-Length ヘッダーフィールドが上流のメッセージ処理装置によって生成または結合されたことを示します。その場合、受信者は、メッセージ本文の長さを決定したりメッセージを転送したりする前に、メッセージを無効として拒否するか、または重複したフィールド値をその 10 進数値を含む単一の有効な Content-Length フィールドに置き換えなければなりません (MUST)。

注: メッセージのフレーミングのための HTTP による Content-Length の使用は、MIME における同じフィールドの使用 ("message/external-body" メディアタイプ内でのみ使用される任意のフィールド) とは大きく異なります。

3.3.3. メッセージ本文の長さ​

メッセージ本文の長さは、次のいずれかによって (優先順に) 決定されます:

  1. HEAD リクエストへの任意のレスポンス、および 1xx (Informational)、204 (No Content)、または 304 (Not Modified) ステータスコードを持つ任意のレスポンスは、メッセージ内に存在するヘッダーフィールドにかかわらず、常にヘッダーフィールド後の最初の空行で終端されるため、メッセージ本文を含むことはできません。

  2. CONNECT リクエストへの任意の 2xx (Successful) レスポンスは、ヘッダーフィールドを締めくくる空行の直後に接続がトンネルになることを示します。クライアントは、そのようなメッセージで受信した Content-Length または Transfer-Encoding ヘッダーフィールドを無視しなければなりません (MUST)。

  3. Transfer-Encoding ヘッダーフィールドが存在し、chunked 転送コーディング (セクション 4.1) が最終エンコーディングである場合、メッセージ本文の長さは、転送コーディングがデータが完了したことを示すまで、チャンク化されたデータを読み込んでデコードすることによって決定されます。

Transfer-Encoding ヘッダーフィールドがレスポンスに存在し、chunked 転送コーディングが最終エンコーディングでない場合、メッセージ本文の長さは、サーバーによって接続が閉じられるまで接続を読み込むことによって決定されます。Transfer-Encoding ヘッダーフィールドがリクエストに存在し、chunked 転送コーディングが最終エンコーディングでない場合、メッセージ本文の長さは確実に決定できません。サーバーは、400 (Bad Request) ステータスコードで応答し、その後接続を閉じなければなりません (MUST)。

Transfer-Encoding と Content-Length の両方のヘッダーフィールドを持つメッセージを受信した場合、Transfer-Encoding が Content-Length を上書きします。そのようなメッセージは、リクエスト密輸 (セクション 9.5) またはレスポンス分割 (セクション 9.4) を実行しようとする試みを示す可能性があり、エラーとして扱うべきです。送信者は、そのようなメッセージを下流に転送する前に、受信した Content-Length フィールドを除去しなければなりません (MUST)。

  1. Transfer-Encoding なしで、かつ異なるフィールド値を持つ複数の Content-Length ヘッダーフィールド、または無効な値を持つ単一の Content-Length ヘッダーフィールドのいずれかを持つメッセージを受信した場合、メッセージのフレーミングは無効であり、受信者はそれを回復不能なエラーとして扱わなければなりません (MUST)。これがリクエストメッセージである場合、サーバーは 400 (Bad Request) ステータスコードで応答し、その後接続を閉じなければなりません (MUST)。これがプロキシによって受信されたレスポンスメッセージである場合、プロキシはサーバーへの接続を閉じ、受信したレスポンスを破棄し、クライアントに 502 (Bad Gateway) レスポンスを送信しなければなりません (MUST)。これがユーザーエージェントによって受信されたレスポンスメッセージである場合、ユーザーエージェントはサーバーへの接続を閉じ、受信したレスポンスを破棄しなければなりません (MUST)。

  2. Transfer-Encoding なしで有効な Content-Length ヘッダーフィールドが存在する場合、その 10 進数値がオクテット単位で予想されるメッセージ本文の長さを定義します。示されたオクテット数が受信される前に送信者が接続を閉じるか受信者がタイムアウトした場合、受信者はメッセージを不完全と見なし、接続を閉じなければなりません (MUST)。

  3. これがリクエストメッセージであり、上記のいずれにも該当しない場合、メッセージ本文の長さは 0 です (メッセージ本文は存在しません)。

  4. それ以外の場合、これは宣言されたメッセージ本文の長さを持たないレスポンスメッセージであるため、メッセージ本文の長さは、サーバーが接続を閉じる前に受信したオクテット数によって決定されます。

正常に完了した接続閉鎖区切りのメッセージと、ネットワーク障害によって中断された部分的に受信したメッセージとを区別する方法はないため、サーバーは、可能な限りエンコーディングまたは長さで区切られたメッセージを生成すべきです (SHOULD)。接続閉鎖区切り機能は、主に HTTP/1.0 との後方互換性のために存在します。

サーバーは、メッセージ本文を含むが Content-Length を含まないリクエストを、411 (Length Required) で応答することによって拒否してもかまいません (MAY)。

chunked 以外の転送コーディングが適用されていない限り、メッセージ本文を含むリクエストを送信するクライアントは、メッセージ本文の長さが事前に既知である場合、chunked 転送コーディングではなく有効な Content-Length ヘッダーフィールドを使用すべきです (SHOULD)。一部の既存のサービスは、chunked 転送コーディングを理解していても、chunked に対して 411 (Length Required) ステータスコードで応答するためです。これは通常、そのようなサービスが、呼び出される前に content-length を必要とし、処理前にリクエスト全体をバッファリングすることができないか、あるいは望まないゲートウェイを介して実装されているためです。

メッセージ本文を含むリクエストを送信するユーザーエージェントは、サーバーが HTTP/1.1 (またはそれ以降) のリクエストを処理することを知らない場合、有効な Content-Length ヘッダーフィールドを送信しなければなりません (MUST)。そのような知識は、特定のユーザー構成の形、または以前に受信したレスポンスのバージョンを記憶することによる場合があります。

接続上の最後のリクエストへの最終レスポンスが完全に受信され、なお読み込むべき追加データが残っている場合、ユーザーエージェントは、残りのデータを破棄するか、そのデータが先行するレスポンス本文の一部として属するかどうかを判断しようと試みてもかまいません (MAY)。これは、先行するメッセージの Content-Length 値が不正確である場合に当てはまる可能性があります。クライアントは、そのような余分なデータを別個のレスポンスとして処理、キャッシュ、または転送してはなりません (MUST NOT)。そのような動作はキャッシュポイズニングに対して脆弱になるためです。

3.4. 不完全なメッセージの処理​

不完全なリクエストメッセージ (通常は、キャンセルされたリクエストまたは発生したタイムアウト例外による) を受信したサーバーは、接続を閉じる前にエラーレスポンスを送信してもかまいません (MAY)。

不完全なレスポンスメッセージ (接続が時期尚早に閉じられた場合、または chunked であるとされる転送コーディングのデコードが失敗した場合に発生し得ます) を受信したクライアントは、そのメッセージを不完全として記録しなければなりません (MUST)。不完全なレスポンスに対するキャッシュ要件は、[RFC7234] のセクション 3 で定義されています。

レスポンスがヘッダーセクションの途中で (空行を受信する前に) 終端し、ステータスコードがレスポンスの完全な意味を伝えるためにヘッダーフィールドに依存している可能性がある場合、クライアントはその意味が伝えられたと仮定できません。クライアントは、次に取るべき行動を決定するために、リクエストを繰り返す必要がある場合があります。

chunked 転送コーディングを使用するメッセージ本文は、エンコーディングを終端するサイズ 0 のチャンクが受信されていない場合、不完全です。有効な Content-Length を使用するメッセージは、受信したメッセージ本文のサイズ (オクテット単位) が Content-Length によって与えられた値より小さい場合、不完全です。chunked 転送コーディングも Content-Length も持たないレスポンスは、接続の閉鎖によって終端されるため、ヘッダーセクションが無傷で受信されていれば、受信したメッセージ本文のオクテット数にかかわらず完全と見なされます。

3.5. メッセージ解析の堅牢性​

古い HTTP/1.0 のユーザーエージェント実装は、行末で終端されていないメッセージ本文の内容を読み込めなかった一部の初期のサーバーアプリケーションの回避策として、POST リクエストの後に余分な CRLF を送信する場合があります。HTTP/1.1 のユーザーエージェントは、リクエストの前に、または後に余分な CRLF を付けてはなりません (MUST NOT)。リクエストメッセージ本文を行末で終端させたい場合、ユーザーエージェントは、終端する CRLF オクテットをメッセージ本文の長さの一部として数えなければなりません (MUST)。

堅牢性のために、リクエスト行を受信して解析することを期待しているサーバーは、リクエスト行の前に受信した少なくとも 1 つの空行 (CRLF) を無視すべきです (SHOULD)。

開始行およびヘッダーフィールドの行終端子は CRLF という並びですが、受信者は、単一の LF を行終端子として認識し、先行する任意の CR を無視してもかまいません (MAY)。

リクエスト行とステータス行の文法ルールは、各構成要素が単一の SP オクテットで区切られることを要求していますが、受信者は代わりに空白で区切られた単語境界で解析し、CRLF 終端子を除き、先行または後続の空白を無視しながら、任意の形式の空白を SP 区切り文字として扱ってもかまいません (MAY)。そのような空白には、次のオクテットの 1 つ以上が含まれます: SP、HTAB、VT (%x0B)、FF (%x0C)、または単独の CR。ただし、メッセージの受信者が複数いて、それぞれが堅牢性について独自の解釈を持っている場合、寛容な解析はセキュリティ脆弱性をもたらす可能性があります (セクション 9.5 を参照してください)。

HTTP リクエストメッセージのみを待ち受けているサーバー、または開始行から見て HTTP リクエストメッセージと思われるものを処理しているサーバーが、上記の堅牢性の例外を除いて HTTP-message 文法に一致しないオクテット列を受信した場合、サーバーは 400 (Bad Request) レスポンスで応答すべきです (SHOULD)。