8. 表現データとメタデータ (Representation Data and Metadata)
8.1. 表現データ (Representation Data)
HTTPメッセージに関連付けられた表現データは、メッセージのコンテンツとして提供されるか、またはメッセージのセマンティクスとターゲットURIによって参照されます。表現データは、表現メタデータヘッダーフィールドによって定義された形式とエンコーディングになっています。
表現データのデータ型は、Content-TypeヘッダーフィールドとContent-Encodingヘッダーフィールドによって決定されます。これらは、2層の順序付けられたエンコーディングモデルを定義します:
representation-data := Content-Encoding( Content-Type( data ) )
8.2. 表現メタデータ (Representation Metadata)
表現ヘッダーフィールドは、表現に関するメタデータを提供します。メッセージがコンテンツを含む場合、表現ヘッダーフィールドはそのデータをどのように解釈するかを記述します。HEADリクエストへのレスポンスでは、表現ヘッダーフィールドは、同じリクエストがGETであった場合にコンテンツに含まれていたであろう表現データを記述します。
8.3. Content-Type
「Content-Type」ヘッダーフィールドは、関連する表現のメディアタイプを示します:メッセージコンテンツに含まれる表現、またはメッセージセマンティクスによって決定される選択された表現のいずれかです。示されたメディアタイプは、データ形式と、Content-Encodingによって示されるコンテンツコーディングがデコードされた後、受信したメッセージセマンティクスの範囲内で受信者がそのデータをどのように処理することを意図しているかの両方を定義します。
Content-Type = media-type
メディアタイプはSection 8.3.1で定義されています。フィールドの例は次のとおりです:
Content-Type: text/html; charset=ISO-8859-4
コンテンツを含むメッセージを生成する送信者は、そのメッセージでContent-Typeヘッダーフィールドを生成すべきです (SHOULD)。ただし、送信者が含まれる表現の意図されたメディアタイプを知らない場合を除きます。Content-Typeヘッダーフィールドが存在しない場合、受信者は、メディアタイプを「application/octet-stream」([RFC2046]、Section 4.5.1) と仮定するか、またはデータを検査してそのタイプを判断してもよい (MAY) です。
実際には、リソース所有者は、与えられた表現に対して正しいContent-Typeを提供するように、オリジンサーバーを常に正しく設定しているわけではありません。一部のユーザーエージェントは、コンテンツを検査し、特定の場合に受信したタイプを上書きします (たとえば、[Sniffing] を参照)。この「MIMEスニッフィング」は、データについて誤った結論を導くリスクがあり、ユーザーを追加のセキュリティリスク (たとえば、「特権昇格」) にさらす可能性があります。さらに、異なるメディアタイプが同じデータ形式を使用するが、そのデータの意図された処理のみが異なる場合がよくあり、これはデータを単独で検査することによって区別することはできません。スニッフィングが実装されている場合、実装者は、ユーザーがそれを無効にできる手段を提供することが奨励されます。
Content-Typeはシングルトンフィールドとして定義されていますが、誤って複数回生成されることがあり、結果として結合されたフィールド値がリストのように見えます。受信者は、多くの場合、リストの最後の構文的に有効なメンバーを使用することによって、このエラーを処理しようとしますが、異なる実装が異なるエラー処理動作を持つ場合、相互運用性とセキュリティの問題につながる可能性があります。
8.3.1. メディアタイプ (Media Type)
HTTPは、オープンで拡張可能なデータ型付けと型ネゴシエーションを提供するために、Content-Type (Section 8.3) およびAccept (Section 12.5.1) ヘッダーフィールドでメディアタイプ [RFC2046] を使用します。メディアタイプは、データ形式とさまざまな処理モデルの両方を定義します:メッセージコンテキストに従ってそのデータをどのように処理するか。
media-type = type "/" subtype parameters
type = token
subtype = token
type/subtypeの後に、名前/値ペアの形式でセミコロン区切りのパラメータ (Section 5.6.6) が続く場合があります (MAY)。パラメータの存在または非存在は、メディアタイプレジストリ内のその定義に応じて、メディアタイプの処理に重要である可能性があります。
トークン生成規則に一致するパラメータ値は、引用符なしで送信できます。ただし、無効な文字を含むパラメータ値 (つまり、トークン生成規則に一致しない) は、送信時に二重引用符で引用されなければなりません (MUST) (Section 5.6.4)。
parameter = parameter-name "=" parameter-value
parameter-name = token
parameter-value = ( token / quoted-string )
注記: メディアタイプパラメータの一部の受信者は、それらを大文字と小文字を区別する方法で扱います。一般的に、パラメータ名には小文字を使用し、パラメータ値には最も一般的なケースを使用することをお勧めします。
メディアタイプは、[BCP13] で定義された手順に従ってIANAに登録されるべきです (ought to)。
注記: 他のヘッダーフィールドの一部の類似の構造とは異なり、メディアタイプパラメータは、「=」文字の周りに空白 (「悪い」空白であっても) を許可しません。
8.3.2. Charset
HTTPは、Content-Type (Section 8.3) およびAccept-Charset (非推奨; Section 12.5.2) ヘッダーフィールドで文字セット名を使用して、テキスト表現の文字エンコーディングスキームを示したりネゴシエートしたりします。文字セットは、大文字と小文字を区別しないトークンで識別されます。
charset = token
文字セット名は、[RFC2978] のSection 2で定義された手順に従って、IANAの「Character Sets」レジストリ (http://www.iana.org/assignments/character-sets) に登録されるべきです (ought to)。
注記: メディアタイプの「charset」パラメータは、特定のメディアタイプ定義に応じて異なるセマンティクスを持つ可能性があります。
「charset」パラメータは、テキストコンテンツのメディアタイプでよく使用されます。そのようなメディアタイプを定義する標準は、相互運用性を向上させる可能性がある場合、特定の文字セットの使用を規定すべきですが (ought to)、HTTPのユーザーと実装者は、受信したコンテンツの解釈に影響する場合、文字セットを明示的に指定することを強く推奨されます。これは、メディアタイプ定義が文字セットパラメータがない場合に文字セットをデフォルトとする場合 (「text」メディアタイプでよくあるケース) でも同様です。
8.3.3. マルチパートタイプ (Multipart Types)
MIMEは、いくつかの「multipart」タイプを提供します -- 単一のメッセージコンテンツ内の1つ以上の表現のカプセル化です。すべてのマルチパートタイプは、[RFC2046] のSection 5.1で定義されているように、共通の構文を共有し、メディアタイプ値の一部として境界パラメータを含みます。メッセージコンテンツ自体がプロトコル要素です。送信者は、ボディパート間の改行を表すためにCRLFのみを生成しなければなりません (MUST)。
HTTPメッセージフレーミングは、メッセージボディ長の指標としてマルチパート境界を使用しませんが、コンテンツを生成または処理する実装によって使用される可能性があります。たとえば、「multipart/form-data」タイプは、[RFC7578] で説明されているように、リクエストでフォームデータを運ぶためによく使用され、「multipart/byteranges」タイプは、一部の206 (Partial Content) レスポンスで使用するためにこの仕様で定義されています (Section 15.3.7を参照)。
8.4. Content-Encoding
「Content-Encoding」ヘッダーフィールドは、メディアタイプに固有のものを超えて、表現に適用されたコンテンツコーディングを示し、したがって、Content-Typeヘッダーフィールドで参照されるメディアタイプのデータを取得するために適用する必要があるデコードメカニズムを示します。Content-Encodingは、主に、基礎となるメディアタイプのアイデンティティを失うことなく、表現のデータを圧縮できるようにするために使用されます。
Content-Encoding = #content-coding
その使用例は次のとおりです:
Content-Encoding: gzip
1つ以上のエンコーディングが表現に適用されている場合、エンコーディングを適用した送信者は、適用された順序でコンテンツコーディングをリストするContent-Encodingヘッダーフィールドを生成しなければなりません (MUST)。「identity」という名前のコーディングは、Accept-Encodingでの特別な役割のために予約されているため、含めるべきではない (SHOULD NOT) ことに注意してください。
エンコーディングパラメータに関する追加情報は、この仕様で定義されていない他のヘッダーフィールドによって提供される可能性があります。
Transfer-Encoding ([HTTP/1.1] のSection 6.1) とは異なり、Content-Encodingにリストされているコーディングは表現の特性です。表現はコード化された形式で定義され、表現に関する他のすべてのメタデータは、メタデータ定義で特に指定されていない限り、コード化された形式に関するものです。通常、表現は、レンダリングまたは類似の使用の直前にのみデコードされます。
メディアタイプに固有のエンコーディングが含まれている場合、たとえば常に圧縮されているデータ形式の場合、そのエンコーディングは、たまたまコンテンツコーディングの1つと同じアルゴリズムであっても、Content-Encodingで再述されることはありません。このようなコンテンツコーディングは、何らかの奇妙な理由で、表現を形成するために2回目に適用された場合にのみリストされます。同様に、オリジンサーバーは、一部のユーザーエージェントが各レスポンスの処理で異なる動作をするため (たとえば、自動解凍とコンテンツのレンダリングの代わりに「名前を付けて保存...」ダイアログを開く)、コーディングがContent-TypeまたはContent-Encodingの一部として定義されているかどうかのみが異なる複数の表現として同じデータを公開することを選択できます。
リクエストメッセージ内の表現に受け入れられないコンテンツコーディングがある場合、オリジンサーバーは415 (Unsupported Media Type) のステータスコードで応答してもよい (MAY) です。
8.4.1. コンテンツコーディング (Content Codings)
コンテンツコーディング値は、表現に適用された、または適用できるエンコーディング変換を示します。コンテンツコーディングは、主に、基礎となるメディアタイプのアイデンティティを失うことなく、情報を失うことなく、表現を圧縮したり、有用に変換したりできるようにするために使用されます。多くの場合、表現はコード化された形式で保存され、直接送信され、最終的な受信者によってのみデコードされます。
content-coding = token
すべてのコンテンツコーディングは大文字と小文字を区別せず、Section 16.6.1で定義されているように、「HTTP Content Coding Registry」内に登録されるべきです (ought to)。それらは、Accept-Encoding (Section 12.5.3) およびContent-Encoding (Section 8.4) ヘッダーフィールドで使用されます。
この仕様では、次のコンテンツコーディングが定義されています:
- compress (およびx-compress):Section 8.4.1.1を参照。
- deflate:Section 8.4.1.2を参照。
- gzip (およびx-gzip):Section 8.4.1.3を参照。
8.4.1.1. Compress Coding
「compress」コーディングは、UNIXファイル圧縮プログラム「compress」によって一般的に生成される適応型Lempel-Ziv-Welch (LZW) コーディング [Welch] です。受信者は、「x-compress」を「compress」と同等と見なすべきです (SHOULD)。
8.4.1.2. Deflate Coding
「deflate」コーディングは、Lempel-Ziv (LZ77) 圧縮アルゴリズムとHuffmanコーディングの組み合わせを使用する「deflate」圧縮データストリーム [RFC1951] を含む「zlib」データ形式 [RFC1950] です。
注記: 一部の非準拠実装は、zlibラッパーなしで「deflate」圧縮データを送信します。
8.4.1.3. Gzip Coding
「gzip」コーディングは、gzipファイル圧縮プログラム [RFC1952] によって一般的に生成される32ビット巡回冗長検査 (CRC) を持つLZ77コーディングです。受信者は、「x-gzip」を「gzip」と同等と見なすべきです (SHOULD)。
8.5. Content-Language
「Content-Language」ヘッダーフィールドは、表現の対象となる視聴者の自然言語を記述します。これは、表現内で使用されるすべての言語と同等ではない可能性があることに注意してください。
Content-Language = #language-tag
言語タグはSection 8.5.1で定義されています。Content-Languageの主な目的は、ユーザーが自分の好みの言語に従って表現を識別および区別できるようにすることです。したがって、コンテンツがデンマーク語を読む視聴者のみを対象としている場合、適切なフィールドは次のとおりです:
Content-Language: da
Content-Languageが指定されていない場合、デフォルトは、コンテンツがすべての言語の視聴者を対象としていることです。これは、送信者がそれを特定の自然言語に固有であるとは考えていないか、または送信者がそれがどの言語を対象としているかを知らないことを意味する可能性があります。
複数の視聴者を対象としているコンテンツの場合、複数の言語がリストされる場合があります (MAY)。たとえば、元のマオリ語と英語のバージョンで同時に提示される「ワイタンギ条約」の表現には、次のものが必要です:
Content-Language: mi, en
ただし、表現内に複数の言語が存在するからといって、それが複数の言語視聴者を対象としているわけではありません。例としては、「ラテン語の最初のレッスン」などの初心者向けの言語入門書があり、これは明らかに英語を読む視聴者が使用することを意図しています。この場合、Content-Languageは適切に「en」のみを含めるべきです。
Content-Languageは、任意のメディアタイプに適用される場合があります (MAY) -- テキストドキュメントに限定されません。
8.5.1. 言語タグ (Language Tags)
[RFC5646] で定義されている言語タグは、人間が他の人間に情報を伝達するために話す、書く、またはその他の方法で伝える自然言語を識別します。コンピュータ言語は明示的に除外されています。
HTTPは、Accept-LanguageおよびContent-Languageヘッダーフィールド内で言語タグを使用します。Accept-Languageは、Section 12.5.4で定義されたより広い言語範囲生成規則を使用しますが、Content-Languageは、以下で定義される言語タグ生成規則を使用します。
language-tag = <Language-Tag, [RFC5646]のSection 2.1を参照>
言語タグは、1つ以上の大文字と小文字を区別しないサブタグのシーケンスであり、各サブタグはハイフン文字 ("-"、%x2D) で区切られます。ほとんどの場合、言語タグは、関連する言語の広いファミリーを識別する主要言語サブタグ (たとえば、「en」= 英語) で構成され、オプションでその言語の範囲を絞り込んだり絞り込んだりする一連のサブタグが続きます (たとえば、「en-CA」= カナダで伝達される英語の変種)。言語タグ内では空白は許可されていません。タグの例は次のとおりです:
fr, en-US, es-419, az-Arab, x-pig-latin, man-Nkoo-GN
詳細については、[RFC5646] を参照してください。
8.6. Content-Length
「Content-Length」ヘッダーフィールドは、関連する表現のデータ長を、10進数の非負整数のオクテット数として示します。コンテンツとして表現を転送する場合、Content-Lengthは、フレーミングを区切るために使用できるように (たとえば、[HTTP/1.1] のSection 6.2)、囲まれたデータの量を特に参照します。完全な表現が期待される他のケースでは、Content-Lengthは表現の現在選択されている長さを参照します。
Content-Length = 1*DIGIT
例は次のとおりです:
Content-Length: 3495
メソッドが囲まれたコンテンツの意味を定義し、Transfer-Encodingを送信していない場合、ユーザーエージェントはリクエストでContent-Lengthを送信すべきです (SHOULD)。たとえば、Content-Lengthヘッダーフィールドは、値が0 (空のコンテンツを示す) の場合でも、通常、POSTリクエストで送信されます。
リクエストメッセージにコンテンツが含まれておらず、メソッドセマンティクスがそのようなデータを予期していない場合、ユーザーエージェントはContent-Lengthヘッダーフィールドを送信すべきではありません (SHOULD NOT)。
サーバーは、HEADリクエスト (Section 9.3.2) への応答でContent-Lengthヘッダーフィールドを送信してもよい (MAY) です。サーバーは、同じリクエストがGETメソッドを使用していた場合にレスポンスのコンテンツで送信されていたであろうオクテットの10進数に等しいフィールド値でない限り、そのような応答でContent-Lengthを送信してはなりません (MUST NOT)。
サーバーは、条件付きGETリクエスト (Section 15.4.5) への304 (Not Modified) レスポンスでContent-Lengthヘッダーフィールドを送信してもよい (MAY) です。サーバーは、同じリクエストへの200 (OK) レスポンスのコンテンツで送信されていたであろうオクテットの10進数に等しいフィールド値でない限り、そのような応答でContent-Lengthを送信してはなりません (MUST NOT)。
サーバーは、1xx (Informational) または204 (No Content) のステータスコードを持つ応答でContent-Lengthヘッダーフィールドを送信してはなりません (MUST NOT)。サーバーは、CONNECTリクエスト (Section 9.3.6) への2xx (Successful) レスポンスでContent-Lengthヘッダーフィールドを送信してはなりません (MUST NOT)。
上記で定義されたケースを除いて、Transfer-Encodingがない場合、オリジンサーバーは、完全なヘッダーセクションを送信する前にコンテンツサイズがわかっている場合、Content-Lengthヘッダーフィールドを送信すべきです (SHOULD)。これにより、ダウンストリーム受信者は転送の進行状況を測定し、自分のフレーミング境界を知り、後続のリクエストのために接続を再利用できるようになります。
Content-LengthはHTTP/1.1でメッセージの区切りに使用されるため、そのフィールド値は、メッセージフレーミングがHTTP/1.1ルールの対象ではない場合でも、受信者によるメッセージの解析方法に影響を与える可能性があります。値が表現の実際のデータ長と一致しない場合、結果は、状況に応じて、悪いメッセージフレーミングから潜在的なリクエストスマグリングまたはレスポンス分割まで、さまざまです。
送信者は、Transfer-Encodingヘッダーフィールドを含むメッセージでContent-Lengthヘッダーフィールドを送信してはなりません (MUST NOT)。
注記: HTTPのメッセージフレーミングでのContent-Lengthの使用は、MIMEでの同じフィールドの使用とは大きく異なります。MIMEでは、「message/external-body」メディアタイプ内でのみ使用されるオプションのフィールドです。
8.7. Content-Location
「Content-Location」ヘッダーフィールドは、このメッセージのコンテンツ内の表現に対応する特定のリソースの識別子として使用できるURIを参照します。言い換えれば、このメッセージの生成時にこのURIでGETリクエストを実行した場合、200 (OK) レスポンスには、このメッセージのコンテンツとして囲まれているのと同じ表現が含まれます。
Content-Location = absolute-URI / partial-URI
Content-Location値は、ターゲットURI (Section 7.1) の置き換えではありません。それは表現メタデータです。[RFC2557] のSection 4でMIMEボディパート用に定義された同じ名前のヘッダーフィールドと同じ構文とセマンティクスを持っています。ただし、HTTPメッセージでの出現は、HTTP受信者に対していくつかの特別な意味を持ちます。
Content-Locationが2xx (Successful) レスポンスメッセージに含まれ、その値がターゲットURIと同じスキーム、authority、およびパスを持つURIを参照する場合、受信者は、コンテンツをそのターゲットリソースの現在の表現と見なしてもよい (MAY) です。GET (Section 9.3.1) またはHEAD (Section 9.3.2) リクエストの場合、これは、サーバーによってContent-Locationが提供されていない場合のデフォルトのセマンティクスと同じです。PUT (Section 9.3.4) またはPOST (Section 9.3.3) のような状態変更リクエストの場合、それは、サーバーのレスポンスコンテンツにそのターゲットリソースの現在の表現が含まれていることを意味し、したがって、アクションについてのみ報告する可能性のある表現 (たとえば、「成功しました!」) と区別されます。これにより、オーサリングアプリケーションは、後続のGETリクエストを必要とすることなく、ローカルコピーを更新できます。
Content-Locationが2xx (Successful) レスポンスメッセージに含まれ、そのフィールド値がターゲットURIと異なるURIを参照する場合、オリジンサーバーは、URIが囲まれた表現に対応する異なるリソースの識別子であると主張します。このような主張は、両方の識別子が同じリソース所有者を共有する場合にのみ信頼できますが、これはHTTPを介してプログラム的に判断することはできません。
-
GETまたはHEADリクエストへの応答の場合、これは、ターゲットURIがコンテンツネゴシエーションの対象となるリソースを参照し、Content-Locationフィールド値が選択された表現のより具体的な識別子であることを示します。
-
POSTリクエストへの201 (Created) レスポンスの場合、Content-Locationフィールド値は、新しいリソースに対応する現在の表現を含むリソースへの参照です。
それ以外の場合、そのようなContent-Locationは、このコンテンツが要求されたアクションのステータスを報告する表現であり、同じレポートが指定されたURIで (GETによる将来のアクセスのために) 利用可能であることを示します。たとえば、POSTリクエストを介して行われた購入トランザクションには、200 (OK) レスポンスのコンテンツとして領収書ドキュメントが含まれる場合があります。Content-Locationフィールド値は、将来同じ領収書のコピーを取得するための識別子を提供します。
リクエストメッセージでContent-Locationを送信するユーザーエージェントは、その値が、ユーザーエージェントが囲まれた表現のコンテンツを (そのユーザーエージェントによって行われた変更の前に) 最初に取得した場所を参照していることを述べています。言い換えれば、ユーザーエージェントは、元の表現のソースへのバックリンクを提供しています。
リクエストメッセージでContent-Locationフィールドを受信するオリジンサーバーは、情報を、表現とともに保存されるメタデータではなく、一時的なリクエストコンテキストとして扱わなければなりません (MUST)。オリジンサーバーは、そのコンテキストを使用してリクエストの処理をガイドしたり、ソースリンクやバージョニングメタデータなど、他の用途のために保存したりしてもよい (MAY) です。ただし、オリジンサーバーは、そのようなコンテキスト情報を使用してリクエストセマンティクスを変更してはなりません (MUST NOT)。
たとえば、クライアントがネゴシエートされたリソースでPUTリクエストを行い、オリジンサーバーがそのPUT (リダイレクトなし) を受け入れた場合、そのリソースの新しい状態は、そのPUTで提供された1つの表現と一致することが期待されます。Content-Locationは、ネゴシエートされた表現の1つだけを更新するための逆コンテンツ選択識別子の形式として使用することはできません。ユーザーエージェントが後者のセマンティクスを望んでいた場合、PUTをContent-Location URIに直接適用していたはずです。
8.8. バリデータフィールド (Validator Fields)
リソースメタデータは、事前条件 (Section 13) 内で使用して条件付きリクエスト (Section 13.1) を行うことができる場合、「バリデータ」と呼ばれます。
バリデータフィールドは、選択された表現 (Section 3.2) の現在のバリデータを伝えます。
安全なリクエストへの応答では、バリデータフィールドは選択された表現 (Section 3.2) を記述します。ステータスコードセマンティクスに応じて、与えられた応答の選択された表現は、必ずしも応答コンテンツとして囲まれた表現と同じではないことに注意してください。
状態変更リクエストへの成功した応答では、バリデータフィールドは、リクエストの処理の結果として以前に選択された表現を置き換えた新しい表現を記述します。
たとえば、201 (Created) レスポンスのETagヘッダーフィールドは、リクエストによって作成されたリソースのバリデータを伝え、PUTへの200 (OK) レスポンスのETagヘッダーフィールドは、PUTリクエストの結果として以前に選択された表現を置き換えた新しい表現のバリデータを伝えます。
この仕様では、リソースの状態を観察し、リクエストの事前条件をテストするために一般的に使用される2つの形式のメタデータを定義しています:変更日 (Section 8.8.2) と不透明なエンティティタグ (Section 8.8.3)。さまざまな設計上の考慮事項に関する追加情報は、Section 13.2にあります。
8.8.1. 弱いバリデータと強いバリデータ (Weak versus Strong)
バリデータには2つのフレーバーがあります:強いまたは弱い。弱いバリデータは生成が簡単ですが、比較にはあまり役立ちません。強いバリデータは比較には理想的ですが、効率的に生成することが非常に困難 (そして時には不可能) な場合があります。すべての形式のリソースが同じ強度のバリデータに準拠することを課すのではなく、HTTPは使用中のバリデータのタイプを公開し、弱いバリデータを事前条件として使用できる場合に制限を課します。
「強いバリデータ」は、GETへの200 (OK) レスポンスのコンテンツで観察可能な表現データへの変更が発生するたびに値が変更される表現メタデータです。
強いバリデータは、表現データへの変更以外の理由で変更される可能性があります。たとえば、表現メタデータの意味的に重要な部分が変更された場合 (たとえば、Content-Type) などですが、リモートキャッシュやオーサリングツールが保持する保存された応答を無効にする必要がある場合にのみ値を変更することが、オリジンサーバーの最善の利益になります。
キャッシュエントリは、有効期限に関係なく、任意に長い期間持続する可能性があります。したがって、キャッシュは、遠い過去に取得したバリデータを使用してエントリを検証しようとする可能性があります。強いバリデータは、時間の経過とともに特定のリソースに関連するすべての表現のすべてのバージョンで一意です。ただし、異なるリソースの表現間での一意性の意味はありません (つまり、同じ強いバリデータが複数のリソースの表現に同時に使用されている可能性があり、それらの表現が同等であることを意味するものではありません)。
実際には、さまざまな強いバリデータが使用されています。最良のものは、厳密なリビジョン管理に基づいており、表現への各変更により、表現がGETにアクセスできるようになる前に、常に一意のノード名とリビジョン識別子が割り当てられます。応答ヘッダーセクションが送信される前にデータが利用可能であり、検証リクエストが受信されるたびにダイジェストを再計算する必要がない場合、表現データに適用される衝突耐性ハッシュ関数も十分です。ただし、リソースに、メタデータのみが異なる異なる表現がある場合、たとえば同じデータ形式を共有するメディアタイプでのコンテンツネゴシエーションで発生する可能性がある場合、オリジンサーバーは、それらの表現を区別するために、バリデータに追加情報を組み込む必要があります。
対照的に、「弱いバリデータ」は、表現データへのすべての変更に対して変更されない可能性がある表現メタデータです。この弱さは、値の計算方法の制限 (たとえば、クロック解像度)、リソースのすべての可能な表現に対して一意性を保証できないこと、または一意のデータシーケンスではなく、自己決定された同等性のセットによって表現をグループ化したいという要望によるものである可能性があります。
オリジンサーバーは、以前の表現を現在の表現の代替として受け入れられないと見なす場合は常に、弱いエンティティタグを変更すべきです (SHOULD)。言い換えれば、弱いエンティティタグは、オリジンサーバーがキャッシュに古い応答を無効にしてほしいときは常に変更すべきです (ought to)。
たとえば、動的測定に基づいて毎秒内容が変化する天気レポートの表現は、キャッシュされた表現が妥当な期間 (おそらくサーバーの負荷や天気の質に基づいて動的に調整される) 有効であるようにするために、(オリジンサーバーの観点から) 同じ弱いバリデータを持つ同等の表現のセットにグループ化される可能性があります。同様に、表現の変更時刻が1秒の解像度でのみ定義されている場合、表現が1秒間に2回変更され、それらの変更の間に取得される可能性がある場合、弱いバリデータである可能性があります。
同様に、バリデータが、与えられたリソースの2つ以上の表現によって同時に共有されている場合、それらの表現が同一の表現データを持っていない限り、バリデータは弱いです。たとえば、オリジンサーバーが、gzipコンテンツコーディングが適用された表現に対して、コンテンツコーディングがない表現と同じバリデータを送信する場合、そのバリデータは弱いです。ただし、2つの同時表現は、表現メタデータのみが異なる場合、同じ強いバリデータを共有できます。たとえば、同じ表現データに対して2つの異なるメディアタイプが利用可能な場合などです。
強いバリデータは、キャッシュ検証、部分コンテンツ範囲、および「更新の損失」回避を含む、すべての条件付きリクエストに使用できます。弱いバリデータは、クライアントが以前に取得した表現データとの正確な等価性を必要としない場合にのみ使用できます。たとえば、キャッシュエントリを検証する場合や、Webトラバーサルを最近の変更に制限する場合などです。
8.8.2. Last-Modified
レスポンスの「Last-Modified」ヘッダーフィールドは、リクエストの処理の終了時に決定される、オリジンサーバーが選択された表現が最後に変更されたと信じる日時を示すタイムスタンプを提供します。
Last-Modified = HTTP-date
その使用例は次のとおりです:
Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT
8.8.2.1. 生成 (Generation)
オリジンサーバーは、最終変更日が合理的かつ一貫して決定できる選択された表現のすべてに対してLast-Modifiedを送信すべきです (SHOULD)。条件付きリクエストおよびキャッシュの鮮度の評価 ([CACHING]) での使用により、不要な転送を大幅に削減し、サービスの可用性とスケーラビリティを大幅に改善できるためです。
表現は通常、リソースインターフェースの背後にある多くの部分の合計です。最終変更時刻は、通常、それらの部分のいずれかが変更された最新の時刻です。与えられたリソースに対してその値がどのように決定されるかは、この仕様の範囲を超えた実装の詳細です。HTTPにとって重要なのは、Last-Modifiedヘッダーフィールドの受信者がその値を使用して条件付きリクエストを行い、ローカルにキャッシュされた応答の妥当性をテストする方法です。
オリジンサーバーは、応答のDateフィールド値を生成する時刻にできるだけ近い時刻にLast-Modified値を取得すべきです (SHOULD)。これにより、受信者は、特に表現がレスポンスが生成される時刻の近くで変更される場合、表現の変更時刻を正確に評価できます。
クロック (Section 5.6.7で定義されているように) を持つオリジンサーバーは、サーバーのメッセージ発信時刻 (Date) より後のLast-Modified日付を送信してはなりません (MUST NOT)。最終変更時刻が、オリジンサーバーのクロックに従って将来のある時刻に評価される実装固有のメタデータから派生している場合、オリジンサーバーは、その値をメッセージ発信日付に置き換えなければなりません (MUST)。これにより、将来の変更日がキャッシュ検証に悪影響を及ぼすことを防ぎます。
クロックを持たないオリジンサーバーは、それらの値が信頼できるクロックを持つ他のシステムまたはユーザーによってリソースに関連付けられていない限り、応答にLast-Modified値を割り当ててはなりません (MUST NOT)。
8.8.2.2. 比較 (Comparison)
Last-Modified時刻は、リクエストでバリデータとして使用される場合、次のルールを使用して強いと推定できない限り、暗黙的に弱いです:
-
バリデータがオリジンサーバーによって表現の実際の現在のバリデータと比較されており、かつ
-
そのオリジンサーバーが、提示されたバリデータでカバーされる秒の間に、関連する表現が2回変更されなかったことを確実に知っている。
または
-
バリデータがクライアントによってIf-Modified-Since、If-Unmodified-Since、またはIf-Rangeヘッダーフィールドで使用されようとしており、理由は、クライアントが関連する表現のキャッシュエントリを持っているため、かつ
-
そのキャッシュエントリにDate値が含まれており、これはオリジンサーバーが元の応答を送信した時刻を示し、かつ
-
提示されたLast-Modified時刻がDate値より少なくとも60秒前である。
または
-
バリデータが中間キャッシュによって、表現のキャッシュエントリに格納されているバリデータと比較されており、かつ
-
そのキャッシュエントリにDate値が含まれており、これはオリジンサーバーが元の応答を送信した時刻を示し、かつ
-
提示されたLast-Modified時刻がDate値より少なくとも60秒前である。
この方法は、同じ秒の間にオリジンサーバーによって2つの異なる応答が送信されたが、両方とも同じLast-Modified時刻を持っていた場合、それらの応答の少なくとも1つが、そのLast-Modified時刻に等しいDate値を持っているという事実に依存しています。任意の60秒の制限は、DateとLast-Modified値が異なるクロックから生成されるか、応答の準備中にやや異なる時刻に生成される可能性に対する保護です。実装は、60秒が短すぎると考えられる場合、60秒より大きい値を使用してもよい (MAY) です。
8.8.3. ETag
レスポンスの「ETag」ヘッダーフィールドは、リクエストの処理の終了時に決定される、選択された表現の現在のエンティティタグを提供します。エンティティタグは、同じリソースの複数の表現を区別するための不透明なバリデータであり、それらの複数の表現が時間の経過に伴うリソース状態の変化によるものか、同時に複数の表現が有効であることをもたらすコンテンツネゴシエーションによるものか、またはその両方によるものかに関係ありません。エンティティタグは、不透明な引用符で囲まれた文字列で構成され、オプションで弱さインジケータが前に付けられます。
ETag = entity-tag
entity-tag = [ weak ] opaque-tag
weak = %s"W/"
opaque-tag = DQUOTE *etagc DQUOTE
etagc = %x21 / %x23-7E / obs-text
; 二重引用符を除くVCHAR、およびobs-text
注記: 以前は、opaque-tagはquoted-string ([RFC2616]、Section 3.11) として定義されていました。したがって、一部の受信者はバックスラッシュのエスケープ解除を実行する可能性があります。したがって、サーバーはエンティティタグでバックスラッシュ文字を避けるべきです (ought to)。
エンティティタグは、いくつかの理由で変更日よりも信頼性が高い場合があります:サーバーで利用可能なクロックがない可能性がある、リソースの変更時刻がアクセス制御の目的で将来に設定されている可能性がある、変更時刻の解像度が保存方法によって制限されている、分散システムがクロックの同期に困難を抱えている可能性がある、エンティティタグは、表現をより良く区別するために、Content-Encodingヘッダーフィールドの値などの追加のメタデータを組み込むことができる、などです。
2つのエンティティタグは、そのopaque-tagsが文字ごとに一致する場合、どちらか一方または両方が弱いとタグ付けされているかどうかに関係なく、同等です。
エンティティタグは、強いバリデータまたは弱いバリデータのいずれかになり得ますが、強いがデフォルトです。オリジンサーバーが表現のエンティティタグを提供し、そのエンティティタグの生成が強いバリデータ (Section 8.8.1) のすべての特性を満たさない場合、オリジンサーバーは、その不透明値の前に「W/」(大文字と小文字を区別) を付けることによって、エンティティタグを弱いとマークしなければなりません (MUST)。
ETag: W/"xyzzy"
ETag: ""
8.8.3.1. 生成 (Generation)
エンティティタグの背後にある原理は、サービスの作成者だけが、そのリソースに最も正確で効率的な検証メカニズムを選択するためにリソースの実装を十分に知っており、そのようなメカニズムは、簡単な比較のために単純なオクテットのシーケンスにマッピングできるということです。値は不透明であるため、クライアントが各エンティティタグがどのように構築されているかを認識する必要はありません。
たとえば、すべての変更に実装固有のバージョニングが適用されているリソースは、内部リビジョン番号を、おそらくコンテンツネゴシエーションの分散識別子と組み合わせて使用して、表現を正確に区別する可能性があります。他の実装では、表現コンテンツの衝突耐性ハッシュ、さまざまなファイル属性の組み合わせ、またはサブ秒の解像度を持つ変更タイムスタンプを使用する可能性があります。
オリジンサーバーは、変更の検出が合理的かつ一貫して決定できる選択された表現のすべてに対してETagを送信すべきです (SHOULD)。エンティティタグの条件付きリクエストでの使用とキャッシュの鮮度の評価 ([CACHING]) により、HTTPネットワークトラフィックの大幅な削減が可能になり、サービスのスケーラビリティと信頼性への重要な貢献者になり得るためです。
8.8.3.2. 比較 (Comparison)
比較コンテキストが弱いバリデータの使用を許可するかどうかに応じて、2つのエンティティタグ比較関数があります:
-
強い比較: 両方が弱くなく、そのopaque-tagsが文字ごとに一致する場合、2つのエンティティタグは同等です。
-
弱い比較: そのopaque-tagsが文字ごとに一致する場合、どちらか一方または両方が弱いとタグ付けされているかどうかに関係なく、2つのエンティティタグは同等です。
以下の例は、エンティティタグペアのセットと、弱い比較と強い比較の両方の関数の結果を示しています:
| ETag 1 | ETag 2 | 強い比較 | 弱い比較 |
|---|---|---|---|
| W/"1" | W/"1" | 一致しない | 一致 |
| W/"1" | W/"2" | 一致しない | 一致しない |
| W/"1" | "1" | 一致しない | 一致 |
| "1" | "1" | 一致 | 一致 |
8.8.3.3. 例:コンテンツネゴシエートされたリソースでのエンティティタグの変化
コンテンツネゴシエーション (Section 12.1) の対象となるリソースを考えてみましょう。GETリクエストへの応答で送信される表現は、Accept-Encodingリクエストヘッダーフィールド (Section 12.5.3) に基づいて異なります:
>> Request:
GET /index HTTP/1.1
Host: www.example.com
Accept-Encoding: gzip
>> Response:
HTTP/1.1 200 OK
Date: Fri, 26 Mar 2010 00:05:00 GMT
ETag: "123-a"
Content-Length: 70
Vary: Accept-Encoding
Content-Type: text/plain
Content-Encoding: gzip
[...]
異なるリクエストヘッダーフィールドのセットの場合、サーバーによって異なる表現が送信される可能性があります:
>> Request:
GET /index HTTP/1.1
Host: www.example.com
>> Response:
HTTP/1.1 200 OK
Date: Fri, 26 Mar 2010 00:05:00 GMT
ETag: "123-b"
Content-Length: 400
Vary: Accept-Encoding
Content-Type: text/plain
[...]
これら2つのレスポンスでのエンティティタグの違いは、送信された表現に異なるデータが含まれていることを示しています。このインスタンスで使用される強いエンティティタグは、キャッシュ検証と範囲リクエストの両方に条件付きリクエストを使用することを許可します。
対照的に、事前に生成された表現のバージョンがあるかどうかをチェックせずに、gzipエンコードされた表現をオンザフライで生成するオリジンサーバーは、同等のコンテンツを示すために弱いエンティティタグを使用する可能性があります:
>> Response:
HTTP/1.1 200 OK
Date: Fri, 26 Mar 2010 00:05:00 GMT
ETag: W/"123"
Content-Length: 70
Vary: Accept-Encoding
Content-Type: text/plain
Content-Encoding: gzip
[...]
この場合、サーバーは、表現の圧縮バージョンが非圧縮バージョンと同等であると仮定しますが、同時に、強いバリデータを決定するのに十分にバージョンを追跡していません。