[1] [[HTTP]] の [DFN[[CODE(HTTP)@en[[[Cookie:]]]] [[要求頭欄]]]]は、[[Cookie]] を[[鯖]]に送信するためのものです。 * 仕様書 - [2] [[Netscape Cookie]]: [CITE[Client Side State - HTTP Cookies]] * 処理モデル ;; [16] [[RFC 2109]] と [[RFC 2965]] は、[[利用者エージェント]]は各種規則に基づき [CODE(HTTP)@en[[[Cookie:]]]] [[応答]]頭欄を送信する[['''べきである''']]、としていました。 [SRC[>>14, >>15]] ** 利用者エージェントの処理 [4] [[HTTP]] [[要求]]を構築する際に、[[要求URL]] と[[利用者エージェント]]が保持している [[Cookie]] を比較し、[[一致]]するものであれば [CODE(HTTP)@en[[[Cookie:]]]] [[要求頭欄]]に入れます。 [CODE(HTTP)@en[[[Cookie:]]]] [[欄]]には [[Cookie]] の名前と値の組を [PRE(HTTP example code)[ Cookie: NAME1=OPAQUE_STRING1; NAME2=OPAQUE_STRING2 ... ]PRE] のように並べて記述します。 [SRC[>>2]] [7] 同じ名前の値は、[CODE(HTTP)@en[[[Domain]]]] や [CODE(HTTP)@en[[[Path]]]] が同じなら設定時に古いものが上書きされますが、 違っていれば両方共残ります。その場合には [CODE(HTTP)@en[[[Cookie:]]]] [[頭欄]]にも両方共含められます。 [SRC[>>2]] *** 順序 [9] より具体的な [CODE(HTTP)@en[[[Path]]]] の [[Cookie]] はより一般的な [CODE(HTTP)@en[[[Path]]]] の [[Cookie]] よりも先にくるべきです。例えば [CODE(HTTP)@en[a=1; path=/foo]] と [CODE(HTTP)@en[b=2; path=/foo/bar]] があれば、 [CODE(HTTP)@en[b=2; a=1]] のように送るべきです。 [SRC[>>2]] [8] 同じ [CODE(HTTP)@en[[[Path]]]] の時の名前と値の組の順序は明確に規定されていません。 *** リダイレクト [11] [[リダイレクト]]によって再度 [[HTTP]] [[要求]]を送信する場合であっても、 (新しい [[URL]] に関して) 通常通り適用される [[Cookie]] を調べて [CODE(HTTP)@en[[[Cookie:]]]] [[頭欄]]を構築するべきです。 ** 串の処理 [10] [[串]]は [CODE(HTTP)@en[[[Cookie:]]]] をそのまま[[鯖]]へと転送するべきです。 それがたとえ [CODE(HTTP)@en[[[If-Modified-Since:]]]] つきの[[条件付き要求]]であってもです。 [SRC[>>2]] * 複数の頭欄 [5] [CODE(HTTP)@en[[[Cookie:]]]] [[要求頭欄]]が複数あっても良いのかどうかは仕様上明確になっていません。 * 仕様書から [3] > When requesting a URL from an HTTP server, the browser will match the URL against all cookies and if any of them match, a line containing the name/value pairs of all matching cookies will be included in the HTTP request. Here is the format of that line: > Cookie: NAME1=OPAQUE_STRING1; NAME2=OPAQUE_STRING2 ... ;; [SRC[>>2]] * 歴史 ** RFC の [CODE(HTTP)@en[Cookie:]] 頭欄の定義 [19] [[RFC 2109]], [[RFC 2965]] では [[Netscape Cookie]] とはあまり互換性がない [CODE(HTTP)@en[[[Cookie:]]]] [[頭欄]]が定義されていました [SRC[>>17, >>18]]。 概要: - [20] 名前と値の組が1つ以上含まれるのは [[Netscape Cookie]] と同じでした。 - [35] 名前は [CODE(HTTP)@en[[[token]]]]、値は [CODE(HTTP)@en[[[token]]]] または [CODE(HTTP)@en[[[quoted-string]]]] でなければなりません [SRC[>>17, >>18]]。 - [21] 名前と値の組の前に [[Cookie]] の[[版]]を [CODE(HTTP)@en[[[$Version]]=1]] のように指定することになっていました [SRC[>>17, >>18]]。 -- [22] [DFN[[CODE(HTTP)@en[$Version]]]] には送信する [[Cookie]] に対応する [CODE(HTTP)@en[[[Set-Cookie]]]]、[CODE(HTTP)@en[[[Set-Cookie2]]]] の [CODE(HTTP)@en[[[Version]]]] と同じものを指定することになっていました。それがない時は [CODE(HTTP)[[[0]]]] を使うことになっていました [SRC[>>17, >>18]]。 -- [24] 混在する場合どうするのでしょうか。 -- [33] [CODE(HTTP)@en[[[Set-Cookie]]]], [CODE(HTTP)@en[[[Set-Cookie2]]]] のどちらも [CODE(HTTP)@en[[[Version]]]] は 1 で区別できませんが、それでいいのでしょうか。。。 -- [34] [CODE(HTTP)@en[[[Set-Cookie2]]]] は [CODE(HTTP)@en[[[Version]]]] が必須のはずですが、ない時の規定が残っているのは消し忘れでしょうか。。。 - [25] 名前と値の組の後に [CODE(HTTP)@en[; [[$Path]]=...]] のように[[属性]]を指定することになっていました [SRC[>>17, >>18]]。 -- [26] [DFN[[CODE(HTTP)@en[[[$Path]]]]]] [SRC[>>17, >>18]], [DFN[[CODE(HTTP)@en[[[$Domain]]]]]] [SRC[>>17, >>18]], [DFN[[CODE(HTTP)[[[$Port]]]]]] [SRC[>>18]] がありました。 -- [27] [CODE(HTTP)@en[[[Set-Cookie]]]], [CODE(HTTP)@en[[[Set-Cookie2]]]] に [CODE(HTTP)@en[[[Path]]]], [CODE(HTTP)@en[[[Domain]]]], [CODE(HTTP)@en[[[Port]]]] 各[[属性]]があった場合は同じ値 (または同じように値なし) でなければ[['''なりません''']]でした [SRC[>>17, >>18]]。[[属性]]自体がなかった場合には [CODE(HTTP)@en[[[$Path]]]], [CODE(HTTP)@en[[[$Domain]]]] は省略する[['''べき''']] [SRC[>>17, >>18]]、 [CODE(HTTP)@en[[[$Port]]]] は省略しなければ[['''ならない''']] [SRC[>>18]] とされていました。 -- [28] つまり、[[属性]]がなくて既定値が補われた場合と明示的に値が指定されていた場合は区別して蓄積しておく必要があるということですね。 - [29] 名前と値の組の順序は、[CODE(HTTP)@en[[[Path]]]] がより具体的なものほど前に来る [SRC[>>17, >>18]] とされていました。 -- [30] [[Netscape Cookie]] と同じですね。 -- [31] それ以外の [CODE(HTTP)@en[[[Domain]]]] 等と順序の関係は[RUBYB[規定しない]@en[unspecified]] [SRC[>>17, >>18]] とされていました。 - [32] 名前と値の組同士の区切りは[[後方互換性]]のため [CODE(HTTP)[[[;]]]] とされていました。 一方で将来との互換性のため[[鯖]]は [CODE(HTTP)[[[,]]]] も受け付けなければ[['''ならない''']]とされていて、 [[ABNF]] 構文上もそうなっていました。 [SRC[>>17, >>18]] - [38] [[鯖]]は、 [CODE(char)[[[$]]]] からはじまる名前を特別な意味を持つものとして解釈する[['''べきです''']] [SRC[>>36, >>37]] とされていました。 -- [39] なぜか MUST ではなくて SHOULD でした。 - [40] [CODE(char)[[[$]]]] 付きの[[属性]]は、前から順に調べていって、一番最初の [CODE(char)[[[$]]]] 無しの[[属性]]の手前までは全体に適用される[[属性]]、その後は直前の [CODE(char)[[[$]]]] 無しの[[属性]]に適用される[[属性]]と解釈するとされていました [SRC[>>36]]。 -- [41] この規定は [[RFC 2109]] にはありましたが、なぜか [[RFC 2965]] にはありませんでした。 - [44] [[串]]は自身で勝手に [CODE(HTTP)@en[[[Cookie:]]]] を[[応答]]に付け足しては[['''なりません''']] [SRC[>>42, >>43]]。 [46] [[Netscape Cookie]] の互換性について、次のようなことが言われていました [SRC[>>45]]。 - [47] 旧クライアントは新しい Cookie を受け取ると知らないものは無視し、理解できるものを使って [CODE(HTTP)@en[[[Cookie:]]]] を送る - [48] 新クライアントは Cookie を常に新形式で送る - [49] 旧鯖は「[CODE(HTTP)[[[$]]]」で始まる[[属性]]をそういう [[Cookie]] だと思って無視する -- [50] ただし「[CODE(HTTP)[[[,]]]]」区切りではなく「[CODE(HTTP)[[[;]]]]」区切りだと思っている - [51] 新鯖は「[CODE(HTTP)@en[[[$Version]]]]」の有無で新旧クライアントを区別できる [52] >>46 を読むと一見[[後方互換性]]が保たれていると錯覚してしまいがちですが、 新 Cookie では[[属性]]の値が[[引用文字列]]でもあり得るので、 旧クライアント・旧鯖は引用符も値の一部だと思ってしまうという問題があります。 - [54] [[起源鯖]]はクライアントが新 Cookie を理解すると分かっていないときは、引用符が必要な値に注意するべきです。 [SRC[>>53]] - [55] 新しいクライアントは [[Cookie]] の版がすべて [[RFC 2109]] 以降であるときだけ値を引用符で括るべきです。 [SRC[>>53]] [56] >>48 より新クライアントは常に新 Cookie を送ることになっているので、 常に[[引用文字列]]で送る新クライアントは旧鯖とは正しくやり取りできなくなり、 >>55 のような注意が必要になるわけです。でも >>54 のように注意しろと言われても困った話です。 引用符が必要な値だけど引用符を使えないときは引用符を外していいのでしょうか。 でも外すと [[RFC 2109]] には適合しなくなります。 [57] また、 [[RFC 2109]] は「[CODE(HTTP)[[[=]]]]」の周りの[[空白]]についても、 [[Netscape Cookie]] では認められていなかったので注意するよう書いています [SRC[>>53]]。 *** 仕様書 - [12] [DEL[[[RFC 2109]]]] ([[廃止]]済み) -- [14] [CSECTION@en[4.2.1 General]] -- [17] '''[CSECTION@en[4.3.4 Sending Cookies to the Origin Server]]''' -- [36] [CSECTION@en[4.4 How an Origin Server Interprets the Cookie Header]] -- [42] [CSECTION@en[4.5 Caching Proxy Role]] -- [45] [CSECTION@en[10.1.1 Extended Cookie Header]] -- [53] [CSECTION@en[10.1.3 Punctuation]] - [13] [[RFC 2965]] -- [15] [CSECTION@en[3.2.1 General]] -- [18] '''[CSECTION@en[3.3.4 Sending Cookies to the Origin Server]]''' -- [37] [CSECTION@en[3.4 How an Origin Server Interprets the Cookie Header]] -- [43] [CSECTION@en[3.5 Caching Proxy Role]] * 実装 [58] [CITE[Mojo::Cookie::Request - search.cpan.org]] ([TIME[2010-08-01 16:26:16 +09:00]] 版) [[RFC 2109]] か [[RFC 2965]] の [CODE(HTTP)@en[[[Cookie:]]]] の構文解析に対応しています。 * 関連 [6] [[Cookie]] を設定する [CODE(HTTP)@en[[[Set-Cookie:]]]] [[頭欄]]と同じように[[名前]]と値の組を並べる形式ではありますが、 [CODE(HTTP)@en[[[Set-Cookie:]]]] は1つの名前と値の組を設定するのに対し、 [CODE(HTTP)@en[[[Cookie:]]]] は複数の名前と値の組を1つにまとめて記述できます。