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>

参考

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://learnku.com/docs/pymotw/httpcook...

译文地址:https://learnku.com/docs/pymotw/httpcook...

上一篇 下一篇
讨论数量: 0
发起讨论 只看当前版本


暂无话题~