# `http.cookies` --- HTTP 状态管理

源代码: Lib/http/cookies.py

The `http.cookies` module defines classes for abstracting the concept of cookies, an HTTP state management mechanism. It supports both simple string-only cookies, and provides an abstraction for having any serializable data-type as cookie value.

之前该模块严格应用了 RFC 2109 和 RFC 2068 规范中描述的解析规则。后来人们发现 MSIE 3.0x 并未遵循这些规范中描述的字符规则；目前各种浏览器和服务器在处理 cookie 时也放宽了解析规则。因此，该模块目前使用的解析规则也没有以前那么严格了。

字符集 `string.ascii_letters`, `string.digits` 和 `!#$%&'*+-.^_`|~:` 标明了本模块允许在 cookie 名称中出现的有效字符 (如 `key`)。

在 3.3 版本发生变更: 允许 ':' 作为有效的 cookie 名称字符。

备注

当遇到无效 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 handling for web clients. The `http.cookiejar` and `http.cookies` modules do not depend on each other.

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_decode 的取值范围内，`value_encode()` 和 `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 代码，若在支持 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"（严格模式）：仅在同站请求中发送 Cookie、"Lax"（宽松模式）：在同站请求和顶层导航（如链接跳转）中发送 Cookie，以及 "None"（无限制模式）：在同站和跨站请求中均发送 Cookie。当设置为 "None" 时，必须同时设置 "secure" 属性（要求 Cookie 仅通过 HTTPS 传输），这是现代浏览器的强制要求。

  属性 `partitioned` 提示用户代理这些跨站点 cookie 应当 仅在首次设置 cookie 所在的同一最高层级上下文中可用。要让它被用户代理所接受，你还 必须 设置 `Secure`。

  此外，还建议在设置分块 cookie 时使用 `__Host` 前缀以使其绑定到主机名而非可注册域。请参阅 CHIPS (Cookies Having Independent Partitioned State) 获取完整说明和示例。

  键不区分大小写，默认值为 `''`。

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

  返回 morsel 的字符串形式，适用于作为 HTTP 头部信息进行发送。默认包含所有属性，除非给出 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)

  用字典 values 中的值更新 morsel 字典中的值。若有 values 字典中的键不是有效的 RFC 2109 属性，则会触发错误。

  在 3.5 版本发生变更: 无效键会触发错误。

Morsel.copy(value)

  返回 morsel 对象的浅拷贝。

  在 3.5 版本发生变更: 返回一个 morsel 对象，而非字典。

Morsel.setdefault(key, value=None)

  若 key 不是有效的 RFC 2109 属性则触发错误，否则与 `dict.setdefault()` 相同。

## 示例

The following example demonstrates how to use the `http.cookies` module.

    >>> 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