21.23. "http.cookies" --- HTTPの状態管理
****************************************

**ソースコード:** Lib/http/cookies.py

======================================================================

"http.cookies" モジュールはHTTPの状態管理機能であるcookieの概念を抽象
化、定義しているクラスです。単純な文字列のみで構成されるcookieのほか、
シリアル化可能なあらゆるデータ型でクッキーの値を保持するための機能も備
えています。

このモジュールは元々 **RFC 2109** と **RFC 2068** に定義されている構文
解析の規則を厳密に守っていました。しかし、MSIE 3.0x がこれらの RFC で
定義された文字の規則に従っていないことが判明し、また、現代の多くのブラ
ウザとサーバも Cookie の処理に緩い解析をしており、結局、やや厳密さを欠
く構文解析規則にせざるを得ませんでした。

文字集合 "string.ascii_letters" 、 "string.digits" 、
"!#$%&'*+-.^_`|~:" を、このモジュールは Cookie 名 ("key") として有効と
認めています。

バージョン 3.3 で変更: ':' が有効な Cookie 名の文字として認められまし
た。

注釈:

  不正な cookie に遭遇した場合、 "CookieError" 例外を送出します。その
  ため、ブラウザから持ってきた cookie データをパースするときには常に不
  正なデータに備え "CookieError" 例外を捕捉してください。

exception http.cookies.CookieError

   属性や *Set-Cookie* ヘッダが正しくないなど、 **RFC 2109** に合致し
   ていないときに発生する例外です。

class http.cookies.BaseCookie([input])

   このクラスはキーが文字列、値が "Morsel" インスタンスで構成される辞
   書風オブジェクトです。値に対するキーを設定するときは、値がキーと値
   を含む "Morsel" に変換されることに注意してください。

   *input* が与えられたときは、そのまま "load()" メソッドへ渡されます
   。

class http.cookies.SimpleCookie([input])

   このクラスは "BaseCookie" の派生クラスで、 "value_decode()" は与え
   られた値の正当性を確認するように、 "value_encode()" は "str()" で文
   字列化するようにそれぞれオーバライドします。

参考:

  モジュール "http.cookiejar"
     Web *クライアント* 向けの HTTP クッキー処理です。
     "http.cookiejar" と "http.cookies" は互いに独立しています。

  **RFC 2109** - HTTP State Management Mechanism
     このモジュールが実装しているHTTPの状態管理に関する規格です。


21.23.1. Cookieオブジェクト
===========================

BaseCookie.value_decode(val)

   文字列表現を値にデコードして返します。戻り値の型はどのようなもので
   も許されます。このメソッドは "BaseCookie" において何も実行せず、オ
   ーバーライドされるためにだけ存在します。

BaseCookie.value_encode(val)

   エンコードした値を返します。元の値はどのような型でもかまいませんが
   、戻り値は必ず文字列となります。このメソッドは "BaseCookie" におい
   て何も実行せず、オーバーライドされるためにだけ存在します。

   通常 "value_encode()" と "value_decode()" はともに *value_decode*
   の処理内容から逆算した範囲に収まっていなければなりません。

BaseCookie.output(attrs=None, header='Set-Cookie:', sep='\r\n')

   HTTPヘッダ形式の文字列表現を返します。 *attrs* と *header* はそれぞ
   れ "Morsel" の "output()" メソッドに送られます。 *sep* はヘッダの連
   結に用いられる文字で、デフォルトは "'\r\n'" (CRLF)となっています。

BaseCookie.js_output(attrs=None)

   ブラウザがJavaScriptをサポートしている場合、HTTPヘッダを送信した場
   合と同様に動作する埋め込み可能なJavaScript snippetを返します。

   *attrs* の意味は "output()" と同じです。

BaseCookie.load(rawdata)

   *rawdata* が文字列であれば、 "HTTP_COOKIE" として処理し、その値を
   "Morsel" として追加します。辞書の場合は次と同様の処理をおこないます
   。

      for k, v in rawdata.items():
          cookie[k] = v


21.23.2. Morselオブジェクト
===========================

class http.cookies.Morsel

   **RFC 2109** の属性をキーと値で保持するabstractクラスです。

   Morselは辞書風のオブジェクトで、キーは次のような **RFC 2109** 準拠
   の定数となっています。

   * "expires"

   * "path"

   * "comment"

   * "domain"

   * "max-age"

   * "secure"

   * "version"

   * "httponly"

   "httponly" 属性は、 cookie が HTTP リクエストでのみ送信されて、
   JavaScript からのはアクセスできない事を示します。これはいくつかのク
   ロスサイトスクリプティングの脅威を和らげることを意図しています。

   キーの大小文字は区別されません。そのデフォルト値は "''" です。

   バージョン 3.5 で変更: "__eq__()" は "key" 及び "value" を考慮する
   ようになりました。

Morsel.value

   クッキーの値。

   バージョン 3.5 で非推奨: "value" の割り当てには代わりに "set()" を
   使用してください。

Morsel.coded_value

   実際に送信する形式にエンコードされたcookieの値。

   バージョン 3.5 で非推奨: "coded_value" の割り当てには代わりに
   "set()" を使用してください。

Morsel.key

   cookieの名前。

   バージョン 3.5 で非推奨: "key" の割り当てには代わりに "set()" を使
   用してください。

Morsel.set(key, value, coded_value)

   属性 *key* 、 *value* 、 *coded_value* に値をセットします。

   バージョン 3.5 で非推奨: ドキュメント化されていない *LegalChars* 引
   数は無視され、将来のバージョンでは削除されます。

Morsel.isReservedKey(K)

   *K* が "Morsel" のキーであるかどうかを判定します。

Morsel.output(attrs=None, header='Set-Cookie:')

   MoselをHTTPヘッダ形式の文字列表現にして返します。 *attrs* を指定し
   ない場合、デフォルトですべての属性を含めます。 *attrs* を指定する場
   合、属性をリストで渡さなければなりません。 *header* のデフォルトは
   ""Set-Cookie:"" です。

Morsel.js_output(attrs=None)

   ブラウザがJavaScriptをサポートしている場合、HTTPヘッダを送信した場
   合と同様に動作する埋め込み可能なJavaScript snippetを返します。

   *attrs* の意味は "output()" と同じです。

Morsel.OutputString(attrs=None)

   Moselの文字列表現をHTTPやJavaScriptで囲まずに出力します。

   *attrs* の意味は "output()" と同じです。

Morsel.update(values)

   Morsel 辞書の値を辞書 *values* の値で更新します。*values* 辞書のキ
   ーのいずれかが有効な **RFC 2109** 属性でない場合エラーを送出します
   。

   バージョン 3.5 で変更: 不正なキーではエラーが送出されます。

Morsel.copy(value)

   Morsel オブジェクトの浅いコピーを返します。

   バージョン 3.5 で変更: 辞書ではなく Morsel オブジェクトを返します。

Morsel.setdefault(key, value=None)

   キーが有効な **RFC 2109** 属性でない場合エラーを送出します。そうで
   ない場合は "dict.setdefault()" と同じように振る舞います。


21.23.3. 使用例
===============

次の例は "http.cookies" の使い方を示したものです。

   >>> from http import cookies
   >>> C = cookies.SimpleCookie()
   >>> C["fig"] = "newton"
   >>> C["sugar"] = "wafer"
   >>> print(C) # generate HTTP headers
   Set-Cookie: fig=newton
   Set-Cookie: sugar=wafer
   >>> print(C.output()) # same thing
   Set-Cookie: fig=newton
   Set-Cookie: sugar=wafer
   >>> C = cookies.SimpleCookie()
   >>> C["rocky"] = "road"
   >>> C["rocky"]["path"] = "/cookie"
   >>> print(C.output(header="Cookie:"))
   Cookie: rocky=road; Path=/cookie
   >>> print(C.output(attrs=[], header="Cookie:"))
   Cookie: rocky=road
   >>> C = cookies.SimpleCookie()
   >>> C.load("chips=ahoy; vienna=finger") # load from a string (HTTP header)
   >>> print(C)
   Set-Cookie: chips=ahoy
   Set-Cookie: vienna=finger
   >>> C = cookies.SimpleCookie()
   >>> C.load('keebler="E=everybody; L=\\"Loves\\"; fudge=\\012;";')
   >>> print(C)
   Set-Cookie: keebler="E=everybody; L=\"Loves\"; fudge=\012;"
   >>> C = cookies.SimpleCookie()
   >>> C["oreo"] = "doublestuff"
   >>> C["oreo"]["path"] = "/"
   >>> print(C)
   Set-Cookie: oreo=doublestuff; Path=/
   >>> C = cookies.SimpleCookie()
   >>> C["twix"] = "none for you"
   >>> C["twix"].value
   'none for you'
   >>> C = cookies.SimpleCookie()
   >>> C["number"] = 7 # equivalent to C["number"] = str(7)
   >>> C["string"] = "seven"
   >>> C["number"].value
   '7'
   >>> C["string"].value
   'seven'
   >>> print(C)
   Set-Cookie: number=7
   Set-Cookie: string=seven
