# 20.22. `Cookie` --- HTTPの状態管理

注釈

Python 3 では `Cookie` モジュールは `http.cookies` にリネームされました。ソースコードを 3 用に変換する時は、 2to3 ツールが自動的に import を修正します。

ソースコード: Lib/Cookie.py

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

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

`string.ascii_letters` 、 `string.digits` 、 `!#$%&'*+-.^_`|~` が、このモジュールが Cookie 名 (`key`) での利用に合法である認めている文字集合です。

注釈

正しくない cookie に遭遇した場合、 `CookieError` 例外を送出します。なので、ブラウザから持ってきた cookie データを parse するときには常に `CookieError` 例外を catch して不正な cookie に備えるべきです。

exception `Cookie.``CookieError`

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

class `Cookie.``BaseCookie`([input])

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

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

class `Cookie.``SimpleCookie`([input])

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

class `Cookie.``SerialCookie`([input])

  このクラスは `BaseCookie` の派生クラスで、 `value_decode()` と `value_encode()` をそれぞれ `pickle.loads()` と `pickle.dumps()` を実行するようにオーバーライドします。

  バージョン 2.3 で非推奨: このクラスを使ってはいけません! 信頼できないcookieのデータから pickle 化された値を読み込むことは、あなたのサーバ上で任意のコードを実行するために pickle 化した文字列の作成が可能であることを意味し、重大なセキュリティホールとなります。

class `Cookie.``SmartCookie`([input])

  このクラスは `BaseCookie` の派生クラスで、 `value_decode()` を、値が pickle 化されたデータとして正当なときは `pickle.loads()` を実行、そうでないときはその値自体を返すようにオーバーライドします。また `value_encode()` を、値が文字列以外のときは `pickle.dumps()` を実行、文字列のときはその値自体を返すようにオーバーライドします。

  バージョン 2.3 で非推奨: `SerialCookie` と同じセキュリティ上の注意が当てはまります。

関連して、さらなるセキュリティ上の注意があります。後方互換性のため、 `Cookie` モジュールは `Cookie` というクラス名を `SmartCookie` のエイリアスとしてエクスポートしています。これはほぼ確実に誤った措置であり、将来のバージョンでは削除することが適当と思われます。アプリケーションにおいて `SerialCookie` クラスを使うべきでないのと同じ理由で `Cookie` クラスを使うべきではありません。

参考

`cookielib` モジュール
  Web クライアント 向けの HTTP クッキー処理です。 `cookielib` と `Cookie` は互いに独立しています。
RFC 2109 - HTTP State Management Mechanism
  このモジュールが実装しているHTTPの状態管理に関する規格です。

## 20.22.1. Cookieオブジェクト

`BaseCookie.``value_decode`(val)

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

`BaseCookie.``value_encode`(val)

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

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

`BaseCookie.``output`([attrs[, header[, sep]]])

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

  バージョン 2.5 で変更: デフォルトのセパレータを `'\n'` から、クッキーの使用にあわせた.

`BaseCookie.``js_output`([attrs])

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

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

`BaseCookie.``load`(rawdata)

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

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

## 20.22.2. Morselオブジェクト

class `Cookie.``Morsel`

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

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

  - `expires`
  - `path`
  - `comment`
  - `domain`
  - `max-age`
  - `secure`
  - `version`
  - `httponly`

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

  キーの大小文字は区別されません。

  バージョン 2.6 で追加: `httponly` 属性が追加されました。

`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[, header]])

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

`Morsel.``js_output`([attrs])

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

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

`Morsel.``OutputString`([attrs])

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

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

## 20.22.3. 例

次の例は `Cookie` の使い方を示したものです。

    >>> import Cookie
    >>> C = Cookie.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 = Cookie.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 = Cookie.SimpleCookie()
    >>> C.load("chips=ahoy; vienna=finger") # load from a string (HTTP header)
    >>> print C
    Set-Cookie: chips=ahoy
    Set-Cookie: vienna=finger
    >>> C = Cookie.SimpleCookie()
    >>> C.load('keebler="E=everybody; L=\\"Loves\\"; fudge=\\012;";')
    >>> print C
    Set-Cookie: keebler="E=everybody; L=\"Loves\"; fudge=\012;"
    >>> C = Cookie.SimpleCookie()
    >>> C["oreo"] = "doublestuff"
    >>> C["oreo"]["path"] = "/"
    >>> print C
    Set-Cookie: oreo=doublestuff; Path=/
    >>> C["twix"] = "none for you"
    >>> C["twix"].value
    'none for you'
    >>> C = Cookie.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
    >>> # SerialCookie and SmartCookie are deprecated
    >>> # using it can cause security loopholes in your code.
    >>> C = Cookie.SerialCookie()
    >>> C["number"] = 7
    >>> C["string"] = "seven"
    >>> C["number"].value
    7
    >>> C["string"].value
    'seven'
    >>> print C
    Set-Cookie: number="I7\012."
    Set-Cookie: string="S'seven'\012p1\012."
    >>> C = Cookie.SmartCookie()
    >>> C["number"] = 7
    >>> C["string"] = "seven"
    >>> C["number"].value
    7
    >>> C["string"].value
    'seven'
    >>> print C
    Set-Cookie: number="I7\012."
    Set-Cookie: string=seven