Cookie 今昔物語
概要
Cookie の不幸な歴史と現状、そして将来についてまとめた。
仕様はどこにあるか
Web 上の様々な規格は、誰かが定め、それに皆が合わせるという形で動いている。しかし、Cookie の仕様は誰が決め、どこで規定されているか知っている人は、意外と少ないのではないかと思う。W3C や IETF だと思っている人が多いのではなかろうか。
正解を言ってしまうと、定めたのは 1994 年、Netscape Communications 社であり、文書は http://wp.netscape.com/newsref/std/cookie_spec.html で公開されていた。アクセスしてみればわかる通り、このページはもう存在しないし、Netscape 社自体が AOL に買収されており、今は Mozilla になったというか、消えてなくなっていることを知っている人は多いだろう。当時の文書は例によって Internet Archive の Client Side State - HTTP Cookies (訳) から見ることができる。
実装としては、策定者の Netscape は古くからから (1.1 以前では expires の取り扱いにバグがある事が公開された仕様にも書かれているが) 対応しており、IE では 1996 年公開の 3.0から対応している。
W3C や IETF は何をしていたのか
何もしていなかったわけではない。IETF は Cookie を標準化するため、1997年に RFC 2109 HTTP State Management Mechanism を規定した。しかし、ここで IETF は何を思ったか、当時の実装とは異なる仕様を定めてしまう。具体的には特に機能が増えたわけでもないのに expires が Max-Age に変わっていることを始めとしたいくつかの重大な非互換を含めてしまった。
Microsoft はこの仕様を黙殺し、続くさらに非互換な RFC 2965 ももちろん無視した。Mozilla では RFC 2965 をサポートしようという提案が出されたが、IE が対応していない事を理由に却下されている。
結局これについては IETF の暴走と、Netscape が実装していないのに規格を承認してしったのと、Microsoft がいないのが不幸の始まりなのだが、この手の規格での互換性確保の重要性を物語る事例であろう。(XHTML 2.0 とかね)
Cookie の「仕様」は変わっていないのか
実は事実上の「改訂」が行われている。具体的には HttpOnly 属性の追加がこれにあたる。この2つの拡張はモダンブラウザでは実装されている (IE6+, FF3+, Safari 4, Chrome, Opera 9.5+)。
標準化は諦められたのか
最近になって再度標準化の試みが IETF でなされている。その最新のドラフトでは、Netscape 仕様をベースに各ブラウザの実相を反映したものとなっており、RFC 2109 や RFC 2965 の仕様は取り込まれていない。このような現実路線は HTML5 でも取られているが、歓迎されるべきものだと思う。
文法
現在の事実上の仕様における Set-Cookie と Cookie ヘッダの文法を ABNF にまとめたので以下に示す。これを書くにあたっては、RFC に加えて Suikawiki の記述 を参考にした。
Set-Cookie = "Set-Cookie:" [FWS] a-cookie [FWS] a-cookie = cookie-pair *([FWS] ";" [FWS] cookie-av) cookie-av = expires-av / domain-av / path-av / secure-av / httponly-av cookie-pair = name [FWS] "=" [FWS] value name = http-token value = http-token ; IE6+ doesn't allow CTLs expires-av = "Expires" [FWS] "=" [FWS] cookie-date cookie-date =; not RFC 2822 domain-av = "Domain" [FWS] "=" [FWS] domain-value domain-value = ["."] dot-http-token ; xx.yy doesn't work on IE dot-http-token = "." / http-token path-av = "Path" [FWS] "=" [FWS] path-value path-value = abs_path abs_path = secure-av = "Secure" httponly-av = "HttpOnly" Cookie = "Cookie:" [FWS] cookie-value *([FWS] ";" [FWS] cookie-value) [FWS] # RFC 2068 HTTP/1.1 CHAR = DIGIT = CTL = CR = LF = SP = HT = CRLF = CR LF LWS = [CRLF] 1*( SP | HT ) HEX = "A" | "B" | "C" | "D" | "E" | "F" | "a" | "b" | "c" | "d" | "e" | "f" | DIGIT tspecials = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | <"> | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT token = 1*
追記
draft-abarth-cookie-07 にて以上の文法が次期仕様にマージされた。