# `http.cookies` --- HTTP 狀態管理

原始碼： Lib/http/cookies.py

`http.cookies` 模組定義了 cookie 概念的抽象化的類別，cookie 是一種 HTTP 狀態管理機制。它支援簡單的純字串 cookie，也提供了將任何可序列化的資料型別作為 cookie 值的抽象化。

此模組原先嚴格遵循了 RFC 2109 和 RFC 2068 規範所描述的剖析規則。自從發現 MSIE 3.0x 並不遵循這些規範所描述的字元規則，許多目前的瀏覽器和伺服器也在處理 cookie 時放寬了剖析規則。因此，此模組現在使用的剖析規則比之前的更為寬鬆。

字元集 `string.ascii_letters`、`string.digits` 和 `!#$%&'*+-.^_`|~` 表示此模組在 cookie 名稱 (`key`) 中允許的合法字元集合。

在 3.3 版的變更: Allowed '`:`' as a valid cookie name character.

在 3.15.0a0 (unreleased) 版的變更: Allowed '`"`' as a valid cookie value character.

備註

當遇到無效的 cookie 時，會引發 `CookieError`，因此如果你的 cookie 資料來自瀏覽器，在剖析時你應該總是為無效資料作準備並捕捉 `CookieError`。

exception http.cookies.CookieError

  因為不符合 RFC 2109 而引發的例外：不正確的屬性、不正確的 Set-Cookie 標頭等。

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 cookie 處理。`http.cookiejar` 和 `http.cookies` 模組互不相依。

RFC 2109 - 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 的範圍內是互逆的 (inverse)。

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 片段，如果在支援 JavaScript 的瀏覽器上執行，它的行為會與 HTTP 標頭被傳送的情況相同。

  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 屬性。

  Morsel 是一種類似字典的物件，其鍵的集合是固定的 --- 有效的 RFC 2109 屬性，它們是：

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

  屬性 `httponly` 指定 cookie 僅在 HTTP 請求中傳輸，而不可通過 JavaScript 存取。這是為了減輕某些形式的跨網站腳本攻擊。

  `samesite` 屬性控制瀏覽器要在何時將 cookie 與跨網站請求一起傳送，這有助於減輕 CSRF 攻擊。有效值為 "Strict"（僅在同站請求時傳送）、"Lax"（同站請求和頂層導航時傳送）和 "None"（同站請求和跨站請求時傳送）。使用 "None" 時，必須同時設定 "secure" 屬性，這是現代瀏覽器的要求。

  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 版的變更: 新增對 `partitioned` 屬性的支援。

Morsel.value

  cookie 的值。

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

  回傳適合作為 HTTP 標頭傳送的 Morsel 的字串表示。預設會包含所有屬性，除非有給定 attrs，在此情況下，它應該是一個要使用的屬性的串列。預設的 header 是 `"Set-Cookie:"`。

Morsel.js_output(attrs=None)

  回傳一個可嵌入的 JavaScript 片段，如果在支援 JavaScript 的瀏覽器上執行，它的行為會與 HTTP 標頭被傳送的情況相同。

  attrs 的意義與 `output()` 裡的相同。

Morsel.OutputString(attrs=None)

  回傳表示 Morsel 的字串，不包含周圍任何的 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=\\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
    >>> import json
    >>> C = cookies.SimpleCookie()
    >>> C.load(f'cookies=7; mixins="{json.dumps({"chips": "dark chocolate"})}"; state=gooey')
    >>> print(C)
    Set-Cookie: cookies=7
    Set-Cookie: mixins="{"chips": "dark chocolate"}"
    Set-Cookie: state=gooey