[10] [DFN[[CODE(HTTP)@en[[[Meter:]]]]]] [[ヘッダー]]は、
[[キャッシュ]]に対してその利用回数を[[鯖]]に報告させたり、
利用回数の上限を設定したりする仕組みです。

[97] [[HTTP]] のオプション機能として [[RFC 2227]] で規定されていますが、
ほとんど利用されていません。

[FIG(sequence)[
:C:[[クライアント]]
:P:[[串]]
:S:[[鯖]]
:C -> P:[[要求]]
:P -> S:[[要求]] [CODE(HTTP)@en[[[Connection:]] [[Meter]]]]
:S -> P:[[応答]] [CODE(HTTP)@en[[[Connection:]] [[Meter]]]]
: #P#  :[[応答]]を[[キャッシュ]]
:P -> C:[[応答]]
:C -> P:[[要求]]
: #P#  :[[キャッシュ]]を利用
:P -> C:[[応答]]
: #P#  :しばらくして利用数を報告
:P -> S:[[要求]] [CODE(HTTP)@en[[[Meter:]] [[count]]=1/0]]
:S -> P:[[応答]]
]FIG]

* 仕様書

[REFS[
- [2] [CITE@en[RFC 2227 - Simple Hit-Metering and Usage-Limiting for HTTP]]
( ([TIME[2011-12-18 04:36:26 +09:00]] 版))
<http://tools.ietf.org/html/rfc2227>
]REFS]

* 意味

[6] [CODE(HTTP)@en[[[Meter]]]] は、[[鯖]]から[[串]]に対して[[キャッシュ]]の利用回数を報告するよう求めたり
(hit-metering)、一定回数以上利用したら[[再検証]]することを求めたり (usage-limiting)
することを指示するものです。また、[[串]]から[[鯖]]に対してそのような機能を提供できることを提示したり、
計測結果を伝達したりするためにも使います。

[3] [[串]]において[[キャッシュ]]を用いて[[応答]]を返すと、
[[起源鯖]]はそのことを感知できませんから、[[応答]]が何回返されたか
(すなわち[[アクセス数]]が幾許であるか) を数えることができません。
これは[[広告]]などの目的で不都合であるため、 [CODE(HTTP)@en[[[Cache-Control:]]]]
などによって[[キャッシュ]]を無効化する [[cache-busting]] [SRC[>>2]] と呼ばれる [[hack]]
がしばしば用いられていました。 [CODE(HTTP)@en[[[Meter]]]]
はそれを置き換えることを狙っていました [SRC[>>2]]。

;; ただしすべての [[cache-busting]] を置き換えることを目的とするものではない [SRC[>>2]]
とされています。

** 利用と再利用

[75] 計測や利用制限は[[資源]] ([[URL]]) ごとではなく、
[[蓄積された応答]]ごとに数えます [SRC[>>2]]。

;; 同じ [[URL]] でも [CODE(HTTP)@en[[[Vary:]]]] [[ヘッダー]]の値が異なれば、別のものとして数えます。

[76] 「[RUBYB[利用]@en[use]]」とは、[[蓄積された応答]]を使って
[CODE(HTTP)[[[200]]]] [[応答]]、 [CODE(HTTP)[[[203]]]] [[応答]]、
第0[[バイト]]を含む [CODE(HTTP)[[[206]]]] [[応答]]のいずれかを返すことをいいます [SRC[>>2]]。

;; [77] [[上流]]から[[応答]]を受信し、それを直後に[[下流]]に[[転送]]することは、
「利用」の数には含めません [SRC[>>2]]。以前に[[キャッシュ項目]]として保存したものを使って[[応答]]することのみを数えます。

[78] 「[RUBYB[再利用]@en[reuse]]」とは、 [CODE(HTTP)[[[304]]]]
[[応答]]を返すことをいいます。ただし第0[[バイト]]を含まない[[範囲要求]]に対するものを除きます。
[SRC[>>2]]

;; [79] この「利用」、「再利用」は、[[キャッシュ再利用]]における「再利用」
とは違う意味です。

* 構文

[18] [CODE(HTTP)@en[[[Meter:]]]] [[ヘッダー]]の値は、0個以上の[[指令]]の[[リスト]]
([CODE(HTTP)[#]]) です [SRC[>>2]]。

[FIG(railroad)[
= ?
== [[指令]]
== *
=== [[OWS]]
=== [CODE(HTTP)[[[,]]]]
=== [[OWS]]
=== [[指令]]
]FIG]

;; [[リスト]]ですから、 [CODE(HTTP)@en[[[Cache-Control:]]]] [[ヘッダー]]の[[指令]]の区切りと同じく、
区切り文字は [CODE(HTTP)[[[;]]]] ではなく [CODE(HTTP)[[[,]]]] です。

[65] 他の[[引数]]構文を使った[[ヘッダー]]の多くとは違って、この[[ヘッダー]]の構文は一般的な「[[指令]]」の構文は定めず、
個々の[[指令]]の構文のみが規定されています。しかしそれらを総合すると、
[[指令]]は名前のみか、名前、[CODE(HTTP)[[[=]]]]、値のいずれかです。

[98] 名前は[[大文字・小文字不区別]]の[[字句]]です。

[FIG(railroad)[
= [[字句]]
= ?
== [CODE(HTTP)[[[=]]]]
== 値
]FIG]

;; [66] 値は (他の同様な[[ヘッダー]]とは違って)
[[字句]]とは限りません。
[CODE(HTTP)[[[count]]]] [[指令]]で値に使う [CODE(HTTP)[[[/]]]]
は[[字句]]で使えない文字ですが、[[引用文字列]]とせずに値の一部として使われています。
[[引用文字列]]を使った例はありません。

[99] 値の構文や、値を指定しなければならないか指定してはならないかは、
名前によって決まります。

[67] [[RFC 2227]] の当時は[[空白]]を挿入可能かどうか構文上明記していませんでしたが、
現在の仕様でいうところの [[BWS]] が [CODE(HTTP)[[[=]]]] の前後に挿入されると解釈するべきかもしれません。

* 空のヘッダー

[100] [CODE(HTTP)@en[[[Meter:]]]] [[ヘッダー]]は0個以上の[[指令]]の[[リスト]]ですから、
何も指定しない ([[空文字列]]や[[空白]]のみの文字列とする) こともできます。

[FIG(list)[
- [21] [[要求]]において値が指定されない場合、 [CODE(HTTP)@en[[[will-report-and-limit]]]]
が指定されたのと等価です [SRC[>>2]]。
- [34] [[応答]]において値が指定されない場合、 [CODE(HTTP)@en[[[do-report]]]]
が指定されたのと等価です [SRC[>>2]]。
]FIG]

;; [36] [[空文字列]]の[[ヘッダー]]と非[[空文字列]]の[[ヘッダー]]が同時に別々に指定された時にも >>21 や >>34 が適用されるのかは明記されていませんが、
字面通り解釈すると適用されることになります。複数の同名の[[ヘッダー]]は
[CODE(HTTP)[[[,]]]] 区切りで連結しても同じ意味を表すことになっていますから、
[[空文字列]]の[[ヘッダー]]と[[空文字列]]でない[[ヘッダー]]が連結されることもあります。
とすると[[ヘッダー]]の値である[[リスト]]に[[空文字列]]の要素が含まれている時も
>>21 や >>34 のように解釈するべきなのでしょうか?

[22] 更に、 [CODE(HTTP)@en[[[Connection:]] [[Meter]]]] によって
[CODE(HTTP)@en[[[Meter:]]]] ([[空文字列]])
が暗示され、 [CODE(HTTP)@en[[[Meter:]]]] [[ヘッダー]]は省略できます [SRC[>>2]]。

* 指令

[48] [[指令]]には、[[要求]]で[[串]]が使うものと[[応答]]で[[鯖]]が使うものがあります。

[71] [[指令]]の名前には非省略形と省略形があり、通常は省略形を使う[['''べきです''']]
[SRC[>>2]]。なお両者を混在させても構いません [SRC[>>2]]。

[108] 次の[[指令]]が規定されています。

[FIG(short list)[
- [CODE(HTTP)@en[[[c]]]]
- [CODE(HTTP)@en[[[d]]]]
- [CODE(HTTP)@en[[[e]]]]
- [CODE(HTTP)@en[[[n]]]]
- [CODE(HTTP)@en[[[r]]]]
- [CODE(HTTP)@en[[[t]]]]
- [CODE(HTTP)@en[[[u]]]]
- [CODE(HTTP)@en[[[w]]]]
- [CODE(HTTP)@en[[[x]]]]
- [CODE(HTTP)@en[[[y]]]]
- [CODE(HTTP)@en[[[count]]]]
- [CODE(HTTP)@en[[[do-report]]]]
- [CODE(HTTP)@en[[[dont-report]]]]
- [CODE(HTTP)@en[[[max-reuses]]]]
- [CODE(HTTP)@en[[[max-uses]]]]
- [CODE(HTTP)@en[[[timeout]]]]
- [CODE(HTTP)@en[[[will-report-and-limit]]]]
- [CODE(HTTP)@en[[[wont-ask]]]]
- [CODE(HTTP)@en[[[wont-limit]]]]
- [CODE(HTTP)@en[[[wont-report]]]]
]FIG]

[73] [[指令]]を指定する順序に意味は無いと思われます。

[72] 同じ[[指令]]が複数回指定された時や、矛盾する[[指令]]が指定された時にどう処理するべきかは不明です。

[109] [[IANA登録簿]]は無いようです。

[107] 他の特定の[[指令]]またはすべての[[指令]]が指定されないことによって暗示的に指定されたとみなされる[[指令]]もいくつかあります。

;; [111] 転送量の削減のために敢えてそのような仕組みにしてあるようです。

;; [131] [[指令]]の一覧は >>130 の[[JSON]]ファイルの [CODE[meter_directives]]
に含まれています。
[REFS[
- [130] [CITE@en[data-web-defs/headers.txt at master · manakai/data-web-defs]] ([TIME[2014-11-14 01:35:25 +09:00]] 版) <https://github.com/manakai/data-web-defs/blob/master/doc/headers.txt>
]REFS]

* 文脈

[102] [CODE(HTTP)@en[[[Meter]]]] は次の3つの文脈で使うことができます。
[FIG(list)[
- [103] [[串]]から[[鯖]]に対する[[要求]]で、利用回数の計測や制限を[[串]]が提供できることを示す
- [104] [[鯖]]から[[串]]に対する[[応答]]で、利用回数の計測を[[串]]が実施するべきことや制限回数、あるいは計測や制限を指定するつもりがないことを示す
- [105] [[串]]から[[鯖]]に対する[[要求]]で、計測した利用回数を報告する
]FIG]

[12] [CODE(HTTP)@en[[[Meter:]]]] [[ヘッダー]]は、
[[プロトコルの版]]が [[HTTP/1.1]] [[未満]]の[[メッセージ]]に含めては[['''なりません''']]
[SRC[>>2]]。

[19] この[[ヘッダー]]は複数指定できます [SRC[>>2]]。

[11] [CODE(HTTP)@en[[[Meter:]]]] [[ヘッダー]]を含む[[メッセージ]]は、
[CODE(HTTP)@en[[[Connection:]] [[meter]]]] を含まなければ[['''なりません''']] [SRC[>>2]]。
[CODE(HTTP)@en[[[Meter:]]]] の値が[[空文字列]]になるときは、
[CODE(HTTP)@en[[[Connection:]] [[meter]]]] のみ指定して
[CODE(HTTP)@en[[[Meter:]]]] [[ヘッダー]]自体は省略できます (>>22)。

[106] [[利用者エージェント]]は [CODE(HTTP)@en[[[Meter]]]] を指定してはいけないと思われますが、
明示的な要件とはなっていません。

* 計測部分木

[8] [[起源鯖]]を[[根]]とし、[[起源鯖]]からの[[応答]]の[[転送]]経路上にあって
[CODE(HTTP)@en[[[Meter:]]]] [[ヘッダー]]による計測に対応した[[串]]によって構成される[[木]]のことを[DFN[[RUBYB[計測部分木]@en[metering subtree]]]]
[SRC[>>2]] といいます。

[9] [[起源鯖]]と[[利用者エージェント]]の間には、 [CODE(HTTP)@en[[[Meter:]]]]
[[ヘッダー]]に対応しない[[串]]や、対応しているものの[[上流]]に対応しない[[串]]が存在しているため対応できない[[串]]があるかもしれません。
[[計測部分木]]は、そのような[[串]]も含めた配送経路全体で構成される[[木]]の[[部分木]]となります。

* 串から鯖へ

[20] [[串]]は、利用回数の計測や制限に対応していることを示すため、
また利用回数を報告するため、[[要求]]に [CODE(HTTP)@en[[[Meter]]]]
を含めることができます [SRC[>>2]]。

[110] 計測にも制限にも対応しない[[串]]は、 [CODE(HTTP)@en[[[Meter:]]]] 
[[ヘッダー]]を送信しては[['''なりません''']] [SRC[>>2]]。

[25] [[串]]は[[要求]]に次の[[指令]]を含めて利用回数の計測や制限を求めることができます 
[SRC[>>2]]。
[FIG(list)[
- [26] [DFN[[CODE(HTTP)@en[[[will-report-and-limit]]]]]] ([DFN[[CODE(HTTP)@en[[[w]]]]]]) は、
利用報告を送信する意思があり、利用制限にも従うつもりであることを表します [SRC[>>2]]。
- [27] [DFN[[CODE(HTTP)@en[[[wont-report]]]]]] ([DFN[[CODE(HTTP)@en[[[x]]]]]]) は、
利用制限に従う意志はあるが利用報告は送信しないことを表します [SRC[>>2]]。
- [28] [DFN[[CODE(HTTP)@en[[[wont-limit]]]]]] ([DFN[[CODE(HTTP)@en[[[y]]]]]]) は、
利用制限には従わないが利用報告は返すつもりであることを表します [SRC[>>2]]。
]FIG]

[68] [[串]]は[[要求]]に次の[[指令]]を含めて利用回数の計測結果を報告できます [SRC[>>2]]。
[FIG(list)[
- [49] [CODE(HTTP)@en[[DFN[[[count]]]]=[VAR[...]]/[VAR[...]]]] ([DFN[[CODE(HTTP)@en[[[c]]]]]])
は、[[十進整数]]を表す[[ASCII数字]]列2つを値として指定します。
1つ目の数は[[利用]]、2つ目の数は[[再利用]]の回数を表します。 [SRC[>>2]]
[FIG(railroad)[
= +
== [[ASCII数字]]
= [CODE(HTTP)[[[/]]]]
= +
== [[ASCII数字]]
]FIG]
]FIG]

[51] [CODE(HTTP)@en[[[count]]=0/0]] は情報がありませんから、
送信する[['''べきではありません''']] [SRC[>>2]]。

[50] [[要求]]に [CODE(HTTP)@en[[[count]]]] 以外の[[指令]]が含まれない時は、
[CODE(HTTP)@en[[[will-report-and-limit]]]] を暗示します [SRC[>>2]]。

;; [70] これらの[[指令]]は[[要求]]にのみ含められます [SRC[>>2]]。

* 鯖から串へ

[37] [[鯖]]は[[要求]]に [CODE(HTTP)@en[[[Meter]]]] が含まれており、
計測や制限を[[下流]]に委ねたい場合に、 [CODE(HTTP)@en[[[Meter:]]]]
[[ヘッダー]]を送信できます。 [CODE(HTTP)@en[[[Meter]]]] の送信を拒みたい時にも使えます。

[29] [[鯖]]は[[串]]に[[応答]]を送信する際に、次の[[指令]]を送信することができます [SRC[>>2]]。

[FIG(list)[
- [30] [DFN[[CODE(HTTP)@en[[[do-report]]]]]] ([DFN[[CODE(HTTP)@en[[[d]]]]]]) 
は、利用報告の送信を求めるものです [SRC[>>2]]。
- [31] [DFN[[CODE(HTTP)@en[[[dont-report]]]]]] ([DFN[[CODE(HTTP)@en[[[e]]]]]])
は、利用報告を送信しないことを求めるものです [SRC[>>2]]。
- [32] [CODE(HTTP)@en[[DFN[[[timeout]]]]=...]] ([DFN[[CODE(HTTP)@en[[[t]]]]]])
は、利用報告を送信するまでの[[分]]数を指定するものです [SRC[>>2]]。
値は[[ASCII数字]]列です [SRC[>>2]]。
- [38] [CODE(HTTP)@en[[DFN[[[max-uses]]]]=...]] ([DFN[[CODE(HTTP)@en[[[u]]]]]]) は、
[[応答]]を「利用」する回数の[[上限]]を指定します。
値は[[ASCII数字列]]です。
この数には当該[[応答]]の直後の[[転送]]は含めません。
[SRC[>>2]]
- [39] [CODE(HTTP)@en[[DFN[[[max-reuses]]]]=...]] ([DFN[[CODE(HTTP)@en[[[r]]]]]]) は、
[[応答]]を「再利用」する回数の[[上限]]を指定します。
値は[[ASCII数字列]]です。 [SRC[>>2]]
- [47] [DFN[[CODE(HTTP)@en[[[wont-ask]]]]]] ([DFN[[CODE(HTTP)@en[[[n]]]]]])
は、 [CODE(HTTP)@en[[[Meter]]]] を送らないことを求めるものです [SRC[>>2]]。
]FIG]

;; [41] [[キャッシュ]]が「先読み」のために[[要求]]して [CODE(HTTP)@en[[[max-uses]]]]
が返された場合でも、次の最初の実際の[[クライアント]]からの[[要求]]にその[[キャッシュ項目]]を使って返した時は回数に含まれません [SRC[>>1]]。

[35] [CODE(HTTP)@en[[[dont-report]]]] を含まない [CODE(HTTP)@en[[[Meter:]]]]
[[ヘッダー]]は、 [CODE(HTTP)@en[[[do-report]]]] が指定されたとみなします [SRC[>>2]]。

;; [46] ここで [CODE(HTTP)@en[[[wont-ask]]]] も [CODE(HTTP)@en[[[dont-report]]]]
と同じとみなされると推測されます。

;; [74] この暗示は[[応答]]のみ適用されると思われます。

[112] [CODE(HTTP)@en[[[wont-ask]]]] は [CODE(HTTP)@en[[[dont-report]]]]
を暗示します。 [SRC[>>2]]

[101] [CODE(HTTP)@en[[[timeout]]]] は [CODE(HTTP)@en[[[do-report]]]]
を暗示しています [SRC[>>2]]。 

[42] [[串]]から[[鯖]]に対して表明 (>>20) した機能以外を[[鯖]]から指定されたとしても、
[[串]]はそれを無視する[['''べきです''']] [SRC[>>20]]。

[119] [CODE(HTTP)@en[[[timeout]]]] の値は、
当該[[応答]]が作成されてから利用報告を送信するべき時刻までの[[分]]数を表します [SRC[>>2]]。

;; [69] これらの[[指令]]は[[応答]]にのみ含められます [SRC[>>2]]。

* 利用回数の計測

[122] [[キャッシュ]]に[[蓄積された応答]]は、計測と制限のための次の変数を持ちます [SRC[>>2]]。
[FIG(short list)[
- [VAR[CU]]
- [VAR[CR]]
- [VAR[TU]]
- [VAR[TR]]
- [VAR[MU]]
- [VAR[MR]]
- [VAR[PF]]
]FIG]

;; [123] 「U」が利用、「R」が再利用を表しています。

[80] これらの値は、次のように変化させます [SRC[>>2]]。
[FIG(list)[
- [81] [[応答]]を[[蓄積]]する時に [VAR[CU]], [VAR[CR]] を 0 に初期化します。
- [82] [[応答]]を利用する時に [VAR[CU]], [VAR[TU]] を、
再利用する時に [VAR[CR]], [VAR[TR]] をそれぞれ 1 ずつ増やします。
- [83] [[クライアント]]からの[[要求]]に [CODE(HTTP)@en[[[Meter:]] [[count]]]]
が含まれていれば、その値を [VAR[CU]] と [VAR[CR]] に加えます。
- [85] 利用報告に対する[[応答]]を受信したら、 [VAR[CU]] と [VAR[CR]] 
をそれぞれ利用報告の送信から[[応答]]の受信までの利用と再利用の数に設定します。
- [88] [CODE(HTTP)@en[[[max-uses]]]] を受信したら [VAR[TU]] を、
[CODE(HTTP)@en[[[max-reuses]]]] を受信したら [VAR[TR]] を 0 に設定します。
- [89] [CODE(HTTP)@en[[[max-uses]]]] と [CODE(HTTP)@en[[[max-reuses]]]] を受信したら、 
それぞれ [VAR[MU]] と [VAR[MR]] を指定された値にします。受信しなかったものがあれば、
[[無限大]]とします。
- [93] [CODE(HTTP)@en[[[max-uses]]=0]] を受信した場合で、
その[[応答]]をただちに[[クライアント]]に[[転送]]しない場合には、 [VAR[PF]] フラグを立てます。
- [86] [VAR[PF]] フラグが立った[[応答]]を[[クライアント]]に[[転送]]した場合には、
[VAR[PF]] フラグを落とします。
]FIG]

;; [87] [VAR[PF]] は「prefetch」の意味で、[[串]]が[[先読み]]機能を実装している時に使うことが想定されています。
先読みを実装しない[[串]]は [VAR[PF]] フラグを実装する必要あ貼りません [SRC[>>2]]。

* 利用回数上限の適用

[40] ある[[蓄積された応答]]を使って[[要求]]を処理する場合に[[串]]は次のように動作します
[SRC[>>2]]。
[FIG(list)[
- [90] 「利用」する場合、 [CODE(math)[[VAR[TU]] ≧ [VAR[MU]]]] で
[VAR[PF]] フラグが立っていないなら、[[再検証]]しなければ[['''なりません''']]。
- [91] 「再利用」する場合、 [CODE(math)[[VAR[TR]] ≧ [VAR[MR]]]] なら、
[[再検証]]しなければ[['''なりません''']]。
]FIG]

[92] いずれにせよ、前の[[要求]]を[[転送]]していてその結果を待っているなら、
その[[応答]]が得られる (か時間切れとなる) まで処理を遅延させる[RUBYB[べき]@en[should]]です。
異なる範囲の[[部分要求]]である場合を除き、
[[再検証]]のために同時に複数の[[要求]]を送信する[['''べきではありません''']]。 [SRC[>>2]]

[17] [[応答]]に利用や再利用の回数の制限があり、
その[[応答]]を利用回数制限に対応した[[串]]に[[転送]]する場合には、
それ(ら)や自身で利用回数を分配することができます [SRC[>>2]]。
ただしその決定方法は仕様では定められておらず、実装や設定に任されています。

;; [63] いずれにせよ、[[串]]が [CODE(HTTP)@en[[[max-uses]]]] や
[CODE(HTTP)@en[[[max-reuses]]]] が含まれる [CODE(HTTP)@en[[[Meter:]]]]
[[ヘッダー]]を受信し、その[[ヘッダー]]を[[下流]]の[[串]]に[[転送]]する場合には、
元々指定された値[[以下]]の何らかの値を指定することになります。
すべてを自身が判断したいなら値を 0 にできますし、
すべてを[[下流]]に委ねたいなら元の値のままにできます。
後者の場合は [VAR[MU]] と [VAR[MR]] を 0 にしないといけません。

[128] [[再検証]]に失敗した場合に[[蓄積された応答]]を使って良いのかは不明です。
[CODE(HTTP)@en[[[must-revalidate]]]] 相当と考えるなら、使わないべきでしょうか。

* 利用報告の送信

[113] [[指令]] [CODE(HTTP)@en[[[do-report]]]] が指定された場合、
[[串]]は[[鯖]]に当該[[応答]]に関する利用報告を送信しなければ[['''なりません''']] [SRC[>>2]]。

[114] [[指令]] [CODE(HTTP)@en[[[dont-report]]]] が指定された場合、
[[串]]は[[鯖]]に当該[[応答]]に関する利用報告を送信する[['''べきではありません''']] [SRC[>>2]]。

[53] ある[[応答]]に関して利用報告を送信することを求められている場合、
[[串]]は次の場合に利用報告を送信しなければ[['''なりません''']] [SRC[>>2]]。
[FIG(list)[
- [54] [[クライアント]]からの [CODE(HTTP)@en[[[GET]]]] や
[CODE(HTTP)@en[[[HEAD]]]] の[[条件付き要求]]を[[転送]]する時
- [55] [CODE(HTTP)@en[[[max-uses]]]] 超過により[[条件付きGET]]を[[生成]]する時
- [56] [CODE(HTTP)@en[[[Meter:]] [[timeout]]]] で指定された時間が経過した場合で計測数が 0 
以外の時
- [57] 何らかの理由で計測数が 0 以外の[[キャッシュ項目]]の計測数を削除する時
([[ストレージ]]制約により削除する時や、より新しい[[応答]]を受信して置き換える時など)
]FIG]

;; [58] [[キャッシュ]]は[[キャッシュ項目]]の[[応答]]の本体を削除しても計測数は削除しないこともできます [SRC[>>2]]。
>>57 は計測数を削除する時点を言っています。

[115] [CODE(HTTP)@en[[[timeout]]]] の指定により利用報告を送信する場合は、
その送信のタイミングの精度は±1分で実装する[RUBYB[べき]@en[should]]です。 [SRC[>>2]]

[52] 利用報告の送信には、 (計測対象を明確にするため)
[[条件付き要求]]を使わなければ[['''なりません''']] [SRC[>>2]]。

;; [124] [[実体タグ]]ではなく [CODE(HTTP)@en[[[*]]]] を指定した[[条件付き要求]]でも良いのかどうかは不明です。

[120] 利用報告を含む[[条件付き要求]]で [CODE(HTTP)@en[[[If-Match:]]]] や 
[CODE(HTTP)@en[[[If-None-Match:]]]] を使う場合は、
[[実体タグ]]を複数指定しては[['''なりません''']] [SRC[>>2]]。
[[クライアント]]からの[[条件付き要求]]を[[転送]]する場合 (>>54) 
であっても、[[実体タグ]]が複数指定されている場合は利用報告を送信しません [SRC[>>2]]。

[121] 利用報告を含む[[条件付き要求]]を[[転送]]時に、
条件を表す[[ヘッダー]]を書き換えては[['''なりません''']] [SRC[>>2]]。

[59] [[クライアント]]からの[[要求]]の[[転送]]ではなく[[串]]が[[要求]]を[[生成]]する
>>56 や >>57 の場合には、 [CODE(HTTP)@en[[[HEAD]]]] 
[[要求]]を使わなければ[['''なりません''']] [SRC[>>2]]。
[[串]]はこの [CODE(HTTP)@en[[[HEAD]]]] [[要求]]が失敗しても再試行する必要はありませんが、
正確性のためできるだけ再試行する[['''べきです''']] [SRC[>>2]]。
[[串]]はこの操作の完了まで他の操作を待たせたりする必要はありません [SRC[>>2]]。

;; [60] [[串]]は同じ[[鯖]]への報告を[[持続的接続]]により複数まとめることを強く[RUBYB[推奨]@en[encourage]]されています。

[84] 利用報告は、 [CODE(HTTP)@en[[[Meter:]] [[count]]]] によって行います。その値はそれぞれ
[VAR[CU]] と [VAR[CR]] としなければ[['''なりません''']] [SRC[>>2]]。

;; [61] [CODE(HTTP)@en[[[Meter:]] [[count]]]] を含む[[要求]]を[[クライアント]]から受信し、
それを[[鯖]]に送信する場合、[[下流]]から受信した値を自身の [VAR[CU]] と [VAR[CR]]
に加算し、その結果を [CODE(HTTP)@en[[[Meter:]] [[count]]]]
に設定して[[転送]]することとなります。

* 処理モデル

[4] [CODE(HTTP)@en[[[Meter]]]] は[[串]]または[[起源鯖]]に対するものです [SRC[>>2]]。
[[利用者エージェント]]には適用されません。

;; [129] 明記されていませんが、趣旨からして[[私的キャッシュ]]にも適用されないと思われます。

[13] [[プロトコルの版]]が [[HTTP/1.1]] [[未満]]の[[クライアント]]から送信された
[CODE(HTTP)@en[[[Meter:]]]] [[ヘッダー]]を受け入れては[['''なりません''']] [SRC[>>2]]。

;; [14] これは、[CODE(HTTP)@en[[[Connection:]]]] を正しく処理できない [[HTTP/1.0]]
[[串]]があるためです [SRC[>>2]]。 

** 起源鯖の処理

[23] [[起源鯖]]は、[[要求]]に [CODE(HTTP)@en[[[Meter]]]] が指定されている時、
[[下流]]に計測や制限を委ねるかどうか決定できます。委ねない場合
(や [CODE(HTTP)@en[[[Meter]]]] を実装しない場合) はただ単に 
[CODE(HTTP)@en[[[Meter]]]] を無視して構いません [SRC[>>2]]。

[33] 委ねる場合には、計測や制限を指示する[[指令]]を指定した
[CODE(HTTP)@en[[[Meter:]]]] [[ヘッダー]]を[[応答]]に含めます [SRC[>>2]]。
[[鯖]]は[[串]]が表明した機能以外を要求しては[['''なりません''']] [SRC[>>2]]。

** 串の処理

[5] [[串]]は [CODE(HTTP)@en[[[Meter:]]]] を実装しても構いませんが、
実装しなくても構いません [SRC[>>2]]。

[95] [[ICP]] などで通信しつつ協調して動作する一連の[[串]]は、全体として[[串]]に対する要件を満たさなければ[['''なりません''']] [SRC[>>2]]。

[64] [[鯖]]から [[HTTP/1.1]] 未満の[[応答]]を受信したら、 [[HTTP/1.1]]
以上の[[応答]]を受信するまで、その[[鯖]]には [CODE(HTTP)@en[[[Meter]]]]
を送信する[['''べきではありません''']]。
ただしその[[鯖]]に関して計測や制限を実施中の場合を除きます。 [SRC[>>2]]

[116] [CODE(HTTP)@en[[[wont-ask]]]] が指定された場合、
以後[[串]]は[[鯖]]に対して [CODE(HTTP)@en[[[Meter]]]]
を送信する[['''べきではありません''']]。
[[串]]はこれを最大24時間覚えておく[['''べきです''']]。 [SRC[>>2]]

;; [117] [[鯖]]が [CODE(HTTP)@en[[[Meter]]]] に対応しているものの当該[[資源]]では使わない場合に、転送量の削減のために
[CODE(HTTP)@en[[[Meter]]]] を指定しないことを求めるのが目的のようです。[[串]]が敢えて覚えておいて抑制する効果がどれだけあるのかは謎です。

[118] [[串]]に対して[[要求]]を送信し[[応答]]を受信する[[クライアント]]は、
[[利用者エージェント]]かもしれませんし、他の[[串]]かもしれません。
[[串]]の場合、 [CODE(HTTP)@en[[[Meter]]]] に対応している ([[計測部分木]]の一部である)
かもしれませんし、対応していないかもしれません。

[15] [[クライアント]]が[[計測部分木]]に含まれないなら、[[応答]]を[[転送]]する際に
[CODE(HTTP)@en[[[Meter]]]] を削除し、 [CODE(HTTP)@en[[[Cache-Control:]] [[s-maxage]]=0]]
を含めなければ[['''なりません''']] [SRC[>>2]]。

;; [16] これにより[[計測部分木]]外の[[共有キャッシュ]]が当該[[応答]]を使う前に常に[[計測部分木]]内の[[鯖]]に[[再検証]]しなくてはならなくなりますから、
[[計測部分木]]内の[[串]]が常に利用回数を計測できることとなります。

[24] [[串]]は [CODE(HTTP)@en[[[Meter]]]] を[[転送]]することもできますが、
その場合でも[[串]]に対する要件は満たさなければ[['''なりません''']] [SRC[>>2]]。

;; [7] [[起源鯖]]は [CODE(HTTP)@en[[[Connection:]] [[Meter]]]] 
と指定しなければなりませんから、 [CODE(HTTP)@en[[[Meter]]]] に対応していない[[串]]は 
[CODE(HTTP)@en[[[Connection:]]]] [[ヘッダー]]の規定に従い [CODE(HTTP)@en[[[Meter:]]]]
[[ヘッダー]]を[[転送]]時に削除します。削除せずに[[転送]]するということは、
[CODE(HTTP)@en[[[Meter]]]] を理解できることを表しています。

[43] [[下流]]からの[[要求]]で [CODE(HTTP)@en[[[Meter]]]] を受信した[[串]]は、
自身の[[上流]]に対する義務と整合する範囲でのみこれを無視して構いません。
[CODE(HTTP)@en[[[Meter]]]] がそのような義務に反する場合や、
[[下流]]からの[[要求]]に [CODE(HTTP)@en[[[Meter]]]] が含まれず[[上流]]からの[[応答]]には
[CODE(HTTP)@en[[[Meter]]]] が含まれている場合、
[[転送]]する[[応答]]に [CODE(HTTP)@en[[[Cache-Control:]] [[s-maxage]]=0]]
を追加しなければ[['''なりません''']]。 [CODE(HTTP)@en[[[Expires:]]]]
や [CODE(HTTP)@en[[[Cache-Control:]] [[max-age]]]] は追加したり変更したりする[['''べきではありません''']]。
[SRC[>>2]]

[EG[
[44] [[外向き]]の[[串]]が [CODE(HTTP)@en[[[Meter]]]] を送信してきた時、
自身の[[キャッシュ項目]]に [CODE(HTTP)@en[[[Meter]]]] が含まれていなければ、
[CODE(HTTP)@en[[[Meter]]]] を無視します [SRC[>>2]]。
]EG]

[EG[
[45] [[外向き]]の[[串]]が [CODE(HTTP)@en[[[Meter:]] [[wont-report]]]] を送信してきた時、
自身の[[キャッシュ項目]]に [CODE(HTTP)@en[[[Meter:]] [[do-report]]]]
が含まれていた場合、[[下流]]からの[[要求]]は自身の義務に則したものではありません。
ですから[[転送]]時には [CODE(HTTP)@en[[[Meter]]]] を削除してかわりに
[CODE(HTTP)@en[[[Cache-Control:]] [[s-maxage]]=0]] を追加しなければなりません。 [SRC[>>2]]
]EG]

[94] [[キャッシュ]]しない[[串]]も[[計測部分木]]に加わることが[RUBYB[強く推奨]@en[strongly recommended]]されています。
そのような[[串]]は[[要求]]でも[[応答]]でも [CODE(HTTP)@en[[[Meter:]]]]
[[ヘッダー]]と適当な [CODE(HTTP)@en[[[Connection:]]]] 
[[ヘッダー]]を[[転送]]する[['''べきです''']]。
一旦 [CODE(HTTP)@en[[[Meter:]]]] を[[転送]]しはじめたら、
適当に[[転送]]をやめたりしては[['''なりません''']]。
また [CODE(HTTP)@en[[[Meter:]]]] を含む[[応答]]を元の[[要求]]以外に返しては[['''なりません''']]。
[SRC[>>2]]

[62] [CODE(HTTP)@en[[[Meter:]] [[count]]]] を含む[[要求]]を受信しても、
[[キャッシュ]]から結果を返せるのであれば、[[串]]は[[転送]]せずに[[応答]]を返しても構いません
[SRC[>>2]]。 [CODE(HTTP)@en[[[count]]]] の値は[[串]]の保持している値に加算され (>>83)、
次に[[串]]が利用数を報告する時に使われます。[[キャッシュ]]から結果を返せない時は、
[CODE(HTTP)@en[[[count]]]] を[[上流]]に[[転送]]しなければ[['''なりません''']] [SRC[>>2]]。

* セキュリティー

[96] [[クライアント]]が [CODE(HTTP)@en[[[count]]]] に指定した値が正確であることは一般には保証されません。
[[起源鯖]]も[[計測部分木]]内の[[串]]も、不正な値が指定されることを考慮する必要があります。
[[串]]は [CODE(HTTP)@en[[[Proxy-Authorization:]]]] や[[ホワイトリスト]]などの手段で利用数を中継する[[クライアント]]を制限することもできます [SRC[>>2]]。

[125] [[RFC 2227]] は >>96 の問題を簡単に触れるだけであまり重大に考えていないようですが
(まだ大らかな時代だったからかもしれませんが。)、これは [CODE(HTTP)@en[[[Meter]]]]
の仕組みが[[起源鯖]] (あるいは[[著者]]) が信用できる“身内”の[[串]]の間でしか機能しないことを意味しています。
不正な値を排除するためには第三者が運用する[[串]]が [CODE(HTTP)@en[[[Meter]]]]
を実装していたとしてもそれは利用できず、 [CODE(HTTP)@en[[[Cache-Control:]] [[s-maxage]]]]
に書き換えられて[[転送]]されることとなります。[[串]]は (あったとしても) 
ほとんどが第三者の運用するものですから、元々 [[RFC 2227]] が望んでいた
[[cache-busting]] の解決には全くなりません。

[126] “身内”の[[串]]の間では [CODE(HTTP)@en[[[Meter]]]] を使う必然性はなく、
[[串]]のログファイルに直接アクセスしたり、[[串]]が提供する (通常の [[HTTP鯖]]としての)
アクセス数の計測機能を参照したりすれば十分です。むしろアクセス数以上の任意の情報が得られ、
より有用です。

;; [127] [CODE(HTTP)@en[[[Meter]]]] がほとんど利用されなかったのはこのような問題を解決できなかったからでしょう。
あるいはそもそも [[RFC 2227]] の[[著者]]らの言う [[cache-busting]]
という「問題」が存在すらしていなかったのかもしれません。 ([[RFC 2227]] 
の書かれた時代にはまだ明確にはなっていなかったかもしれませんが、)
[[著者]]の管理下にない[[共有キャッシュ]]は [[Web]] では機能しませんし、
必要性もほとんどありません ([[共有キャッシュ]]参照)。

* 歴史

[1] [CITE@en[draft-ietf-http-hit-metering-00 - Simple Hit-Metering and Usage-Limiting for HTTP]]
( ([TIME[2012-01-20 20:05:43 +09:00]] 版))
<http://tools.ietf.org/html/draft-ietf-http-hit-metering-00>

[REFS[
- [305] [CITE[HTTP-wg Archive: Re: Hit-metering implementations]]
( ([TIME[2014-11-14 01:37:28 +09:00]] 版))
<http://www.hpl.hp.com/personal/ange/archives/http-wg-archive/0023.html>
]REFS]

[132] >>305 には [[RFC 2227]] が出版された後にいくつか実装しようという動きがあるものの、
[[起源鯖]]では[[ログ]]にどう記録するかが問題になるだろう、ただし [[RFC]]
の範囲外である、と状況が説明されています。

;; [133] [[RFC 2227]] は [[Proposed Standard]] なので、実装経験なしでも出版できています。
それにしても実装可能か十分検討せずに標準として出版するとは流石 [[IETF]] ですね。

[REFS[
- [134] [CITE@en[draft-mogul-http-dupsup-00 - Duplicate Suppression in HTTP]] ([TIME[2014-10-26 21:59:10 +09:00]] 版) <https://tools.ietf.org/html/draft-mogul-http-dupsup-00>
- [136] [CITE@en[draft-gupta-efficient-ad-00 - Efficiently transporting ad-carrying web pages]] ([TIME[2014-10-22 06:47:14 +09:00]] 版) <http://tools.ietf.org/html/draft-gupta-efficient-ad-00>
]REFS]

[135] >>134 は同じ著者が提案する別の拡張で、 [CODE(HTTP)@en[[[Meter]]]]
との相互作用も検討していましたが、こちらは [[RFC]] 化すらされていないようです。

[137] >>136 は [[RFC 2227]] を引用して [[cache-busting]] を踏まえた[[広告]]に関する仕組みを提案していましたが、支持を集められなかったようです。

[REFS[
- [138] [CITE@en[RFC 3914 - Open Pluggable Edge Services (OPES) Treatment of IAB Considerations]] ([TIME[2014-11-03 08:42:22 +09:00]] 版) <http://tools.ietf.org/html/rfc3914#section-5.1>
]REFS]

[139] >>138 は [CODE(HTTP)@en[[[Meter]]]] の失敗の原因として[[アクセス数]]以外の
[[IPアドレス]]や[[クッキー]]などを[[起源鯖]]が得られないことを挙げています。