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

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

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

"http.cookies" モジュールは、HTTP の状態管理機構であるクッキーの概念を
抽象化したクラスを定義しています。 単純な文字列だけのクッキーをサポー
トするほか、シリアライズ可能な任意のデータ型をクッキーの値に使うための
抽象化も提供します。

このモジュールは元々 **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"
     ウェブ *クライアント* 向けの 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')

   HTTP ヘッダーとして送信できる文字列表現を返します。 *attrs* と
   *header* は、各 "Morsel" の "output()" メソッドに渡します。 *sep*
   はヘッダーの連結に使い、デフォルトは "'\r\n'" (CRLF) です。

BaseCookie.js_output(attrs=None)

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

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

   バージョン 3.15 で非推奨、バージョン 3.19 で削除予定: このメソッド
   は、ブラウザーにクッキーを設定する JavaScript コード片を生成します
   が、この方法は現在では標準的な方法とも推奨される方法ともみなされて
   いません。 代わりに "output()" を使って HTTP ヘッダーを生成してくだ
   さい。

BaseCookie.load(rawdata)

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

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


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

class http.cookies.Morsel

   **RFC 2109** の属性を持つ、キーと値のペアを抽象化したものです。

   Morsel は辞書のようなオブジェクトで、使用できるキーの集合は固定され
   ています。 キーは **RFC 2109** で有効な次の属性です:

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

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

   "samesite" 属性は、ブラウザーがクロスサイトリクエストでクッキーを送
   信する条件を制御します。 これは CSRF 攻撃の軽減に役立ちます。 有効
   な値は "Strict" (同一サイトへのリクエストだけで送信)、"Lax" (同一サ
   イトへのリクエストとトップレベルのナビゲーションで送信)、 "None" (
   同一サイトへのリクエストとクロスサイトリクエストで送信) です。
   "None" を使う場合、現在のブラウザーの要件に従い、"secure" 属性も設
   定しなければなりません。

   "partitioned" 属性は、これらのクロスサイトクッキーを、最初に設定し
   たときと同じトップレベルのコンテキストでだけ利用できるように *すべ
   き* であるとユーザーエージェントに示します。 ユーザーエージェントが
   これを受け入れるには、"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 で変更: "partitioned" 属性をサポートするようになり
   ました。

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:')

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

Morsel.js_output(attrs=None)

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

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

   バージョン 3.15 で非推奨、バージョン 3.19 で削除予定: このメソッド
   は、ブラウザーにクッキーを設定する JavaScript コード片を生成します
   が、この方法は現在では標準的な方法とも推奨される方法ともみなされて
   いません。 代わりに "output()" を使って HTTP ヘッダーを生成してくだ
   さい。

Morsel.OutputString(attrs=None)

   HTTP ヘッダーや JavaScript で囲まずに、Morsel を表す文字列を返しま
   す。

   *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) # HTTP ヘッダーを生成
   Set-Cookie: fig=newton
   Set-Cookie: sugar=wafer
   >>> print(C.output()) # 同じ結果
   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") # 文字列 (HTTP ヘッダー) から読み込む
   >>> 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 # 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
