13.7. http.cookies — HTTP Cookies
目标:定义用于解析和创建 HTTP cookie 头的类。
http.cookies
模块实现了一个解析器,该解析器可用于分析基本上兼容 RFC 2109 的 cookies 。该实现比标准略微宽松一些,因为 MSIE 3.0x 尚不支持整个标准。
创建和设定一个 Cookie
Cookies 可用来管理基于浏览器应用的状态,因此通常由服务器设置为由客户端存储和返回。最一般的例子是创建单个名值对 cookie 。
http_cookies_setheaders.py
from http import cookies
c = cookies.SimpleCookie()
c['mycookie'] = 'cookie_value'
print(c)
输出是一个合法的 Set-Cookie
头,并准备好作为 HTTP 回复的一部分传递给客户端。
$ python3 http_cookies_setheaders.py
Set-Cookie: mycookie=cookie_value
Morsels
比如期限,路径和域等 cookie 的其他方面也是可以调节的。事实上, RFC 中所有关于 cookies 的属性都可以通过用来表示 cookie 值的 Morsel
对象管理。
http_cookies_Morsel.py
from http import cookies
import datetime
def show_cookie(c):
print(c)
for key, morsel in c.items():
print()
print('key =', morsel.key)
print(' value =', morsel.value)
print(' coded_value =', morsel.coded_value)
for name in morsel.keys():
if morsel[name]:
print(' {} = {}'.format(name, morsel[name]))
c = cookies.SimpleCookie()
# 必须将相应的值通过编码
# 才能装入头部的 cookie
c['encoded_value_cookie'] = '"cookie,value;"'
c['encoded_value_cookie']['comment'] = 'Has escaped punctuation'
# 仅作用于网站一部分的 cookie
c['restricted_cookie'] = 'cookie_value'
c['restricted_cookie']['path'] = '/sub/path'
c['restricted_cookie']['domain'] = 'PyMOTW'
c['restricted_cookie']['secure'] = True
# 只有 5 分钟有效期的 cookie
c['with_max_age'] = 'expires in 5 minutes'
c['with_max_age']['max-age'] = 300 # seconds
# 在特定时间过期的 cookie
c['expires_at_time'] = 'cookie_value'
time_to_live = datetime.timedelta(hours=1)
expires = (datetime.datetime(2009, 2, 14, 18, 30, 14) +
time_to_live)
# 日期时间格式:Wdy, DD-Mon-YY HH:MM:SS GMT
expires_at_time = expires.strftime('%a, %d %b %Y %H:%M:%S')
c['expires_at_time']['expires'] = expires_at_time
show_cookie(c)
这个例子展示了两种让存储的 cookies 过期的办法。一种是将 max-age
设定为以秒计的一个数字,另一种则直接用 expires
来设定过期的日期和时刻。
$ python3 http_cookies_Morsel.py
Set-Cookie: encoded_value_cookie="\"cookie\054value\073\"";
Comment=Has escaped punctuation
Set-Cookie: expires_at_time=cookie_value; expires=Sat, 14 Feb
2009 19:30:14
Set-Cookie: restricted_cookie=cookie_value; Domain=PyMOTW;
Path=/sub/path; Secure
Set-Cookie: with_max_age="expires in 5 minutes"; Max-Age=300
key = encoded_value_cookie
value = "cookie,value;"
coded_value = "\"cookie\054value\073\""
comment = Has escaped punctuation
key = restricted_cookie
value = cookie_value
coded_value = cookie_value
path = /sub/path
domain = PyMOTW
secure = True
key = with_max_age
value = expires in 5 minutes
coded_value = "expires in 5 minutes"
max-age = 300
key = expires_at_time
value = cookie_value
coded_value = cookie_value
expires = Sat, 14 Feb 2009 19:30:14
Cookie
和 Morsel
对象的行为都类似于一个字典对象, Morsel
的关键字集合是固定的:
- expires
- path
- comment
- domain
- max-age
- secure
- version
一个 Cookie
实例的所有关键字就是每一个存储的 cookies 的名称。这些名称也可以通过 Morsel
对象的 key 属性来获得。
编码值
Cookie 头的值需要经过编码才能被正确解析。
http_cookies_coded_value.py
from http import cookies
c = cookies.SimpleCookie()
c['integer'] = 5
c['with_quotes'] = 'He said, "Hello, World!"'
for name in ['integer', 'with_quotes']:
print(c[name].key)
print(' {}'.format(c[name]))
print(' value={!r}'.format(c[name].value))
print(' coded_value={!r}'.format(c[name].coded_value))
print()
Morsel.value
总表示 cookie 解码后的值, 而 Morsel.coded_value
总表示要用来传递给客户的值。这两个值都是而且总是字符串。存储到 cookie 的值如果不是字符串,将自动作转换。
$ python3 http_cookies_coded_value.py
integer
Set-Cookie: integer=5
value='5'
coded_value='5'
with_quotes
Set-Cookie: with_quotes="He said\054 \"Hello\054 World!\""
value='He said, "Hello, World!"'
coded_value='"He said\\054 \\"Hello\\054 World!\\""'
接收和解析 Cookie 头
一旦 Set-Cookie
头被客户端接收,这些 cookies 将在后续的请求中使用一个 Cookie
头回传给服务器。一个输入 Cookie
头字符串可能包含多个以分号 (;
) 隔开的 cookie 值。
Cookie: integer=5; with_quotes="He said, \"Hello, World!\""
cookies 是否可以直接从头部获得还是需要通过 HTTP_COOKIE
环境变量,则取决于网络服务器和所使用的框架。
http_cookies_parse.py
from http import cookies
HTTP_COOKIE = '; '.join([
r'integer=5',
r'with_quotes="He said, \"Hello, World!\""',
])
print('From constructor:')
c = cookies.SimpleCookie(HTTP_COOKIE)
print(c)
print()
print('From load():')
c = cookies.SimpleCookie()
c.load(HTTP_COOKIE)
print(c)
要解码收到的 cookie 头,可以将去掉前缀头的字符串传给 SimpleCookie
来实例化一个对象,或者使用 load()
方法。
$ python3 http_cookies_parse.py
From constructor:
Set-Cookie: integer=5
Set-Cookie: with_quotes="He said, \"Hello, World!\""
From load():
Set-Cookie: integer=5
Set-Cookie: with_quotes="He said, \"Hello, World!\""
其他输出格式
除了使用 Set-Cookie
头以外,服务器也有可能用一段 JavaScript 代码来添加 cookies 到客户端。 SimpleCookie
和 Morsel
通过 js_output()
方法提供 JavaScript 输出。
http_cookies_js_output.py
from http import cookies
import textwrap
c = cookies.SimpleCookie()
c['mycookie'] = 'cookie_value'
c['another_cookie'] = 'second value'
js_text = c.js_output()
print(textwrap.dedent(js_text).lstrip())
结果是一段完整的带有 script
标签的用于设定 cookies 的代码语句。
$ python3 http_cookies_js_output.py
<script type="text/javascript">
<!-- begin hiding
document.cookie = "another_cookie=\"second value\"";
// end hiding -->
</script>
<script type="text/javascript">
<!-- begin hiding
document.cookie = "mycookie=cookie_value";
// end hiding -->
</script>
参考
- 标准库 http.cookies 文档
http.cookiejar
--cookielib
模块,在客户端处理 cookies- RFC 2109 -- HTTP 状态管理机制
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。