利用

Meter: ヘッダー (HTTP)

[10] Meter: ヘッダーは、 キャッシュに対してその利用回数を鯖に報告させたり、 利用回数の上限を設定したりする仕組みです。

[97] HTTP のオプション機能として RFC 2227 で規定されていますが、 ほとんど利用されていません。

C
クライアント
P
串
S
鯖
C -> P
要求
P -> S
要求 Connection: Meter
S -> P
応答 Connection: Meter
#P#
応答をキャッシュ
P -> C
応答
C -> P
要求
#P#
キャッシュを利用
P -> C
応答
#P#
しばらくして利用数を報告
P -> S
要求 Meter: count=1/0
S -> P
応答

仕様書

意味

[6] Meter は、鯖から串に対してキャッシュの利用回数を報告するよう求めたり (hit-metering)、一定回数以上利用したら再検証することを求めたり (usage-limiting) することを指示するものです。また、串から鯖に対してそのような機能を提供できることを提示したり、 計測結果を伝達したりするためにも使います。

[3] 串においてキャッシュを用いて応答を返すと、 起源鯖はそのことを感知できませんから、応答が何回返されたか (すなわちアクセス数が幾許であるか) を数えることができません。 これは広告などの目的で不都合であるため、 Cache-Control: などによってキャッシュを無効化する cache-busting >>2 と呼ばれる hack がしばしば用いられていました。 Meter はそれを置き換えることを狙っていました >>2。

ただしすべての cache-busting を置き換えることを目的とするものではない >>2 とされています。

利用と再利用

[75] 計測や利用制限は資源 (URL) ごとではなく、 蓄積された応答ごとに数えます >>2。

同じ URL でも Vary: ヘッダーの値が異なれば、別のものとして数えます。

[76] 「利用 (use) 」とは、蓄積された応答を使って 200 応答、 203 応答、 第0バイトを含む 206 応答のいずれかを返すことをいいます >>2。

[77] 上流から応答を受信し、それを直後に下流に転送することは、 「利用」の数には含めません >>2。以前にキャッシュ項目として保存したものを使って応答することのみを数えます。

[78] 「再利用 (reuse) 」とは、 304 応答を返すことをいいます。ただし第0バイトを含まない範囲要求に対するものを除きます。 >>2

[79] この「利用」、「再利用」は、キャッシュ再利用における「再利用」 とは違う意味です。

構文

[18] Meter: ヘッダーの値は、0個以上の指令のリスト (#) です >>2。

  1. ?
    1. 指令
    2. *
      1. OWS
      2. ,
      3. OWS
      4. 指令
リストですから、 Cache-Control: ヘッダーの指令の区切りと同じく、 区切り文字は ; ではなく , です。

[65] 他の引数構文を使ったヘッダーの多くとは違って、このヘッダーの構文は一般的な「指令」の構文は定めず、 個々の指令の構文のみが規定されています。しかしそれらを総合すると、 指令は名前のみか、名前、=、値のいずれかです。

[98] 名前は大文字・小文字不区別の字句です。

  1. 字句
  2. ?
    1. =
    2. 値
[66] 値は (他の同様なヘッダーとは違って) 字句とは限りません。 count 指令で値に使う / は字句で使えない文字ですが、引用文字列とせずに値の一部として使われています。 引用文字列を使った例はありません。

[99] 値の構文や、値を指定しなければならないか指定してはならないかは、 名前によって決まります。

[67] RFC 2227 の当時は空白を挿入可能かどうか構文上明記していませんでしたが、 現在の仕様でいうところの BWS が = の前後に挿入されると解釈するべきかもしれません。

空のヘッダー

[100] Meter: ヘッダーは0個以上の指令のリストですから、 何も指定しない (空文字列や空白のみの文字列とする) こともできます。

[36] 空文字列のヘッダーと非空文字列のヘッダーが同時に別々に指定された時にも >>21 や >>34 が適用されるのかは明記されていませんが、 字面通り解釈すると適用されることになります。複数の同名のヘッダーは , 区切りで連結しても同じ意味を表すことになっていますから、 空文字列のヘッダーと空文字列でないヘッダーが連結されることもあります。 とするとヘッダーの値であるリストに空文字列の要素が含まれている時も >>21 や >>34 のように解釈するべきなのでしょうか?

[22] 更に、 Connection: Meter によって Meter: (空文字列) が暗示され、 Meter: ヘッダーは省略できます >>2。

指令

[48] 指令には、要求で串が使うものと応答で鯖が使うものがあります。

[71] 指令の名前には非省略形と省略形があり、通常は省略形を使うべきです >>2。なお両者を混在させても構いません >>2。

[108] 次の指令が規定されています。

[73] 指令を指定する順序に意味は無いと思われます。

[72] 同じ指令が複数回指定された時や、矛盾する指令が指定された時にどう処理するべきかは不明です。

[109] IANA登録簿は無いようです。

[107] 他の特定の指令またはすべての指令が指定されないことによって暗示的に指定されたとみなされる指令もいくつかあります。

[111] 転送量の削減のために敢えてそのような仕組みにしてあるようです。

文脈

[102] Meter は次の3つの文脈で使うことができます。

  • [103] 串から鯖に対する要求で、利用回数の計測や制限を串が提供できることを示す
  • [104] 鯖から串に対する応答で、利用回数の計測を串が実施するべきことや制限回数、あるいは計測や制限を指定するつもりがないことを示す
  • [105] 串から鯖に対する要求で、計測した利用回数を報告する

[12] Meter: ヘッダーは、 プロトコルの版が HTTP/1.1 未満のメッセージに含めてはなりません >>2。

[19] このヘッダーは複数指定できます >>2。

[11] Meter: ヘッダーを含むメッセージは、 Connection: meter を含まなければなりません >>2。 Meter: の値が空文字列になるときは、 Connection: meter のみ指定して Meter: ヘッダー自体は省略できます (>>22)。

[106] 利用者エージェントは Meter を指定してはいけないと思われますが、 明示的な要件とはなっていません。

計測部分木

[8] 起源鯖を根とし、起源鯖からの応答の転送経路上にあって Meter: ヘッダーによる計測に対応した串によって構成される木のことを計測部分木 (metering subtree) >>2 といいます。

[9] 起源鯖と利用者エージェントの間には、 Meter: ヘッダーに対応しない串や、対応しているものの上流に対応しない串が存在しているため対応できない串があるかもしれません。 計測部分木は、そのような串も含めた配送経路全体で構成される木の部分木となります。

串から鯖へ

[20] 串は、利用回数の計測や制限に対応していることを示すため、 また利用回数を報告するため、要求に Meter を含めることができます >>2。

[110] 計測にも制限にも対応しない串は、 Meter: ヘッダーを送信してはなりません >>2。

[25] 串は要求に次の指令を含めて利用回数の計測や制限を求めることができます >>2。

  • [26] will-report-and-limit (w) は、 利用報告を送信する意思があり、利用制限にも従うつもりであることを表します >>2。
  • [27] wont-report (x) は、 利用制限に従う意志はあるが利用報告は送信しないことを表します >>2。
  • [28] wont-limit (y) は、 利用制限には従わないが利用報告は返すつもりであることを表します >>2。

[68] 串は要求に次の指令を含めて利用回数の計測結果を報告できます >>2。

[51] count=0/0 は情報がありませんから、 送信するべきではありません >>2。

[50] 要求に count 以外の指令が含まれない時は、 will-report-and-limit を暗示します >>2。

[70] これらの指令は要求にのみ含められます >>2。

鯖から串へ

[37] 鯖は要求に Meter が含まれており、 計測や制限を下流に委ねたい場合に、 Meter: ヘッダーを送信できます。 Meter の送信を拒みたい時にも使えます。

[29] 鯖は串に応答を送信する際に、次の指令を送信することができます >>2。

[41] キャッシュが「先読み」のために要求して max-uses が返された場合でも、次の最初の実際のクライアントからの要求にそのキャッシュ項目を使って返した時は回数に含まれません >>1。

[35] dont-report を含まない Meter: ヘッダーは、 do-report が指定されたとみなします >>2。

[46] ここで wont-ask も dont-report と同じとみなされると推測されます。
[74] この暗示は応答のみ適用されると思われます。

[112] wont-ask は dont-report を暗示します。 >>2

[101] timeout は do-report を暗示しています >>2。

[42] 串から鯖に対して表明 (>>20) した機能以外を鯖から指定されたとしても、 串はそれを無視するべきです >>20。

[119] timeout の値は、 当該応答が作成されてから利用報告を送信するべき時刻までの分数を表します >>2。

[69] これらの指令は応答にのみ含められます >>2。

利用回数の計測

[122] キャッシュに蓄積された応答は、計測と制限のための次の変数を持ちます >>2。

  • CU
  • CR
  • TU
  • TR
  • MU
  • MR
  • PF

[123] 「U」が利用、「R」が再利用を表しています。

[80] これらの値は、次のように変化させます >>2。

[87] PF は「prefetch」の意味で、串が先読み機能を実装している時に使うことが想定されています。 先読みを実装しない串は PF フラグを実装する必要あ貼りません >>2。

利用回数上限の適用

[40] ある蓄積された応答を使って要求を処理する場合に串は次のように動作します >>2。

[92] いずれにせよ、前の要求を転送していてその結果を待っているなら、 その応答が得られる (か時間切れとなる) まで処理を遅延させるべき (should) です。 異なる範囲の部分要求である場合を除き、 再検証のために同時に複数の要求を送信するべきではありません。 >>2

[17] 応答に利用や再利用の回数の制限があり、 その応答を利用回数制限に対応した串に転送する場合には、 それ(ら)や自身で利用回数を分配することができます >>2。 ただしその決定方法は仕様では定められておらず、実装や設定に任されています。

[63] いずれにせよ、串が max-uses や max-reuses が含まれる Meter: ヘッダーを受信し、そのヘッダーを下流の串に転送する場合には、 元々指定された値以下の何らかの値を指定することになります。 すべてを自身が判断したいなら値を 0 にできますし、 すべてを下流に委ねたいなら元の値のままにできます。 後者の場合は MU と MR を 0 にしないといけません。

[128] 再検証に失敗した場合に蓄積された応答を使って良いのかは不明です。 must-revalidate 相当と考えるなら、使わないべきでしょうか。

利用報告の送信

[113] 指令 do-report が指定された場合、 串は鯖に当該応答に関する利用報告を送信しなければなりません >>2。

[114] 指令 dont-report が指定された場合、 串は鯖に当該応答に関する利用報告を送信するべきではありません >>2。

[53] ある応答に関して利用報告を送信することを求められている場合、 串は次の場合に利用報告を送信しなければなりません >>2。

[58] キャッシュはキャッシュ項目の応答の本体を削除しても計測数は削除しないこともできます >>2。 >>57 は計測数を削除する時点を言っています。

[115] timeout の指定により利用報告を送信する場合は、 その送信のタイミングの精度は±1分で実装するべき (should) です。 >>2

[52] 利用報告の送信には、 (計測対象を明確にするため) 条件付き要求を使わなければなりません >>2。

[124] 実体タグではなく * を指定した条件付き要求でも良いのかどうかは不明です。

[120] 利用報告を含む条件付き要求で If-Match: や If-None-Match: を使う場合は、 実体タグを複数指定してはなりません >>2。 クライアントからの条件付き要求を転送する場合 (>>54) であっても、実体タグが複数指定されている場合は利用報告を送信しません >>2。

[121] 利用報告を含む条件付き要求を転送時に、 条件を表すヘッダーを書き換えてはなりません >>2。

[59] クライアントからの要求の転送ではなく串が要求を生成する >>56 や >>57 の場合には、 HEAD 要求を使わなければなりません >>2。 串はこの HEAD 要求が失敗しても再試行する必要はありませんが、 正確性のためできるだけ再試行するべきです >>2。 串はこの操作の完了まで他の操作を待たせたりする必要はありません >>2。

[60] 串は同じ鯖への報告を持続的接続により複数まとめることを強く推奨 (encourage) されています。

[84] 利用報告は、 Meter: count によって行います。その値はそれぞれ CU と CR としなければなりません >>2。

[61] Meter: count を含む要求をクライアントから受信し、 それを鯖に送信する場合、下流から受信した値を自身の CU と CR に加算し、その結果を Meter: count に設定して転送することとなります。

処理モデル

[4] Meter は串または起源鯖に対するものです >>2。 利用者エージェントには適用されません。

[129] 明記されていませんが、趣旨からして私的キャッシュにも適用されないと思われます。

[13] プロトコルの版が HTTP/1.1 未満のクライアントから送信された Meter: ヘッダーを受け入れてはなりません >>2。

[14] これは、Connection: を正しく処理できない HTTP/1.0 串があるためです >>2。

起源鯖の処理

[23] 起源鯖は、要求に Meter が指定されている時、 下流に計測や制限を委ねるかどうか決定できます。委ねない場合 (や Meter を実装しない場合) はただ単に Meter を無視して構いません >>2。

[33] 委ねる場合には、計測や制限を指示する指令を指定した Meter: ヘッダーを応答に含めます >>2。 鯖は串が表明した機能以外を要求してはなりません >>2。

串の処理

[5] 串は Meter: を実装しても構いませんが、 実装しなくても構いません >>2。

[95] ICP などで通信しつつ協調して動作する一連の串は、全体として串に対する要件を満たさなければなりません >>2。

[64] 鯖から HTTP/1.1 未満の応答を受信したら、 HTTP/1.1 以上の応答を受信するまで、その鯖には Meter を送信するべきではありません。 ただしその鯖に関して計測や制限を実施中の場合を除きます。 >>2

[116] wont-ask が指定された場合、 以後串は鯖に対して Meter を送信するべきではありません。 串はこれを最大24時間覚えておくべきです。 >>2

[117] 鯖が Meter に対応しているものの当該資源では使わない場合に、転送量の削減のために Meter を指定しないことを求めるのが目的のようです。串が敢えて覚えておいて抑制する効果がどれだけあるのかは謎です。

[118] 串に対して要求を送信し応答を受信するクライアントは、 利用者エージェントかもしれませんし、他の串かもしれません。 串の場合、 Meter に対応している (計測部分木の一部である) かもしれませんし、対応していないかもしれません。

[15] クライアントが計測部分木に含まれないなら、応答を転送する際に Meter を削除し、 Cache-Control: s-maxage=0 を含めなければなりません >>2。

[16] これにより計測部分木外の共有キャッシュが当該応答を使う前に常に計測部分木内の鯖に再検証しなくてはならなくなりますから、 計測部分木内の串が常に利用回数を計測できることとなります。

[24] 串は Meter を転送することもできますが、 その場合でも串に対する要件は満たさなければなりません >>2。

[7] 起源鯖は Connection: Meter と指定しなければなりませんから、 Meter に対応していない串は Connection: ヘッダーの規定に従い Meter: ヘッダーを転送時に削除します。削除せずに転送するということは、 Meter を理解できることを表しています。

[43] 下流からの要求で Meter を受信した串は、 自身の上流に対する義務と整合する範囲でのみこれを無視して構いません。 Meter がそのような義務に反する場合や、 下流からの要求に Meter が含まれず上流からの応答には Meter が含まれている場合、 転送する応答に Cache-Control: s-maxage=0 を追加しなければなりません。 Expires: や Cache-Control: max-age は追加したり変更したりするべきではありません。 >>2

[44] 外向きの串が Meter を送信してきた時、 自身のキャッシュ項目に Meter が含まれていなければ、 Meter を無視します >>2。

[45] 外向きの串が Meter: wont-report を送信してきた時、 自身のキャッシュ項目に Meter: do-report が含まれていた場合、下流からの要求は自身の義務に則したものではありません。 ですから転送時には Meter を削除してかわりに Cache-Control: s-maxage=0 を追加しなければなりません。 >>2

[94] キャッシュしない串も計測部分木に加わることが強く推奨 (strongly recommended) されています。 そのような串は要求でも応答でも Meter: ヘッダーと適当な Connection: ヘッダーを転送するべきです。 一旦 Meter: を転送しはじめたら、 適当に転送をやめたりしてはなりません。 また Meter: を含む応答を元の要求以外に返してはなりません。 >>2

[62] Meter: count を含む要求を受信しても、 キャッシュから結果を返せるのであれば、串は転送せずに応答を返しても構いません >>2。 count の値は串の保持している値に加算され (>>83)、 次に串が利用数を報告する時に使われます。キャッシュから結果を返せない時は、 count を上流に転送しなければなりません >>2。

セキュリティー

[96] クライアントが count に指定した値が正確であることは一般には保証されません。 起源鯖も計測部分木内の串も、不正な値が指定されることを考慮する必要があります。 串は Proxy-Authorization: やホワイトリストなどの手段で利用数を中継するクライアントを制限することもできます >>2。

[125] RFC 2227 は >>96 の問題を簡単に触れるだけであまり重大に考えていないようですが (まだ大らかな時代だったからかもしれませんが。)、これは Meter の仕組みが起源鯖 (あるいは著者) が信用できる“身内”の串の間でしか機能しないことを意味しています。 不正な値を排除するためには第三者が運用する串が Meter を実装していたとしてもそれは利用できず、 Cache-Control: s-maxage に書き換えられて転送されることとなります。串は (あったとしても) ほとんどが第三者の運用するものですから、元々 RFC 2227 が望んでいた cache-busting の解決には全くなりません。

[126] “身内”の串の間では Meter を使う必然性はなく、 串のログファイルに直接アクセスしたり、串が提供する (通常の HTTP鯖としての) アクセス数の計測機能を参照したりすれば十分です。むしろアクセス数以上の任意の情報が得られ、 より有用です。

[127] Meter がほとんど利用されなかったのはこのような問題を解決できなかったからでしょう。 あるいはそもそも RFC 2227 の著者らの言う cache-busting という「問題」が存在すらしていなかったのかもしれません。 (RFC 2227 の書かれた時代にはまだ明確にはなっていなかったかもしれませんが、) 著者の管理下にない共有キャッシュは Web では機能しませんし、 必要性もほとんどありません (共有キャッシュ参照)。

歴史

[1] draft-ietf-http-hit-metering-00 - Simple Hit-Metering and Usage-Limiting for HTTP ( ( 版)) <http://tools.ietf.org/html/draft-ietf-http-hit-metering-00>

[132] >>305 には RFC 2227 が出版された後にいくつか実装しようという動きがあるものの、 起源鯖ではログにどう記録するかが問題になるだろう、ただし RFC の範囲外である、と状況が説明されています。

[133] RFC 2227 は Proposed Standard なので、実装経験なしでも出版できています。 それにしても実装可能か十分検討せずに標準として出版するとは流石 IETF ですね。

[135] >>134 は同じ著者が提案する別の拡張で、 Meter との相互作用も検討していましたが、こちらは RFC 化すらされていないようです。

[137] >>136 は RFC 2227 を引用して cache-busting を踏まえた広告に関する仕組みを提案していましたが、支持を集められなかったようです。

[139] >>138 は Meter の失敗の原因としてアクセス数以外の IPアドレスやクッキーなどを起源鯖が得られないことを挙げています。