"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()" をオーバーライドします。 "SimpleCookie" は文字列と
   cookie 値をサポートします。値を設定するとき、 "SimpleCookie" は組み
   込みの "str()" を呼び出して値を文字列に変換します。HTTP から受け取
   った値は文字列として保持されます。

参考:

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

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


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

BaseCookie.value_decode(val)

   文字列表現のタプル "(real_value, coded_value)" を返します。
   "real_value" の型はどのようなものでも許容されます。このメソッドは
   "BaseCookie" においてデコードを行わず、オーバーライドされるためにだ
   け存在します。

BaseCookie.value_encode(val)

   タプル "(real_value, coded_value)" を返します。 *val* の型はどのよ
   うなものでも許容されますが、 "coded_value" は常に文字列に変換されま
   す。このメソッドは "BaseCookie" においてエンコードを行わず、オーバ
   ーライドされるためにだけ存在します。

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

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

   Return a string representation suitable to be sent as HTTP headers.
   *attrs* and *header* are sent to each "Morsel"'s "output()" method.
   *sep* is used to join the headers together, and is by default the
   combination "'\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


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

class http.cookies.Morsel

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

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

      expires
      path
      comment
      domain
      max-age
      secure
      version
      httponly
      samesite
      partitioned

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

   The attribute "samesite" controls when the browser sends the cookie
   with cross-site requests. This helps to mitigate CSRF attacks.
   Valid values are "Strict" (only sent with same-site requests),
   "Lax" (sent with same-site requests and top-level navigations), and
   "None" (sent with same-site and cross-site requests). When using
   "None", the "secure" attribute must also be set, as required by
   modern browsers.

   The attribute "partitioned" indicates to user agents that these
   cross-site cookies *should* only be available in the same top-level
   context that the cookie was first set in. For this to be accepted
   by the user agent, you **must** also set "Secure".

   In addition, it is recommended to use the "__Host" prefix when
   setting partitioned cookies to make them bound to the hostname and
   not the registrable domain. Read CHIPS (Cookies Having Independent
   Partitioned State) for full details and examples.

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

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

   バージョン 3.7 で変更: "key" と "value" 、 "coded_value" 属性は読み
   出し専用です。設定には、 "set()" を使用してください。

   バージョン 3.8 で変更: "samesite" 属性がサポートされました。

   バージョン 3.14 で変更: Added support for the "partitioned"
   attribute.

Morsel.value

   クッキーの値。

Morsel.coded_value

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

Morsel.key

   cookieの名前。

Morsel.set(key, value, coded_value)

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

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()" と同じように振る舞います。


使用例
======

次の例は "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=;";')
   >>> print(C)
   Set-Cookie: keebler="E=everybody; L=\"Loves\"; fudge=;"
   >>> 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
