cookie

environ demo

environ={'HTTP_AUTHORIZATION': 'Bearer: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJidXR0ZXJmbHkiLCJpYXQiOjE1NzUwNDE1NTgsInVzZXJuYW1lIjoid2FuZ2JpbjM0IiwianRpIjoiMWVmMDI0MDQtM2Q3MC00ZmI4LTg2YzUtNTE3MWE0NzkwYTI0IiwiZXhwIjoxNTc1MDcwMzU4fQ.CgEUugRpKMvlCjlYmZ56Xx6G1m6z0bPcrw2u-FTifm4', 'HTTP_REFERER': 'http://127.0.0.1:8585/main', 'SERVER_SOFTWARE': 'CherryPy/3.2.0 Server', 'SCRIPT_NAME': '', 'ACTUAL_SERVER_PROTOCOL': 'HTTP/1.1', 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/api/get_jobs', 'SERVER_PROTOCOL': 'HTTP/1.1', 'QUERY_STRING': '', 'HTTP_USER_AGENT': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36', 'HTTP_CONNECTION': 'keep-alive', 'REMOTE_PORT': '51501', 'SERVER_NAME': 'B000000119924S', 'REMOTE_ADDR': '127.0.0.1', 'wsgi.url_scheme': 'http', 'SERVER_PORT': '8585', 'HTTP_SEC_FETCH_MODE': 'cors', 'HTTP_HOST': '127.0.0.1:8585', 'wsgi.multithread': True, 'HTTP_SEC_FETCH_SITE': 'same-origin', 'REQUEST_URI': '/api/get_jobs', 'HTTP_ACCEPT': 'application/json, text/plain, */*', 'wsgi.version': (1, 0), 'wsgi.run_once': False, 'wsgi.multiprocess': False, 'HTTP_ACCEPT_LANGUAGE': 'zh-CN,zh;q=0.9', 'HTTP_ACCEPT_ENCODING': 'gzip, deflate, br', 'HTTP_COOKIE': 'csrftoken=tcjr7Ps8pJKNrS8JNmB1h7YLz1XKUMWoVn02OoREBuVmSZHn5KLfScHSv7PthuCB'}

测试时可以先将部分 key 剔除

'wsgi.errors': <open file '<stderr>', mode 'w' at 0x107efa1e0>
'wsgi.input': <xlib.cherrypy_wsgiserver.KnownLengthRFile object at 0x108b0b250>

1.1 Django

使用

Django 中 cookie 的保存和存取

保存 cookie: 通过 HttpResponse 类的对象的 set_cookie 方法保存

response.set_cookie('键', '值',max_age)

读取 cookie:通过 HttpRequest 请求对象的 COOKIES 属性(字典类型)读取

request.COOKIES['键']
# 或者:
request.COOKIES.get('键')

django/core/handlers/wsgi.py

@cached_property
def COOKIES(self):
    raw_cookie = get_str_from_wsgi(self.environ, 'HTTP_COOKIE', '')
    return http.parse_cookie(raw_cookie)
  • 解析 cookie:django/http/cookie.py:parse_cookie

    • django/http/cookie.py

Django 是获取到 cookie 字符串,然后将字符串解析为 Dict,不过 Django 在解析时,如果只指定了一个属性,则假定而不是,详情如下

https://bugzilla.mozilla.org/show_bug.cgi?id=169091

django/core/handlers/wsgi.py:WSGIHandler

for c in response.cookies.values():
    response_headers.append((str('Set-Cookie'), str(c.output(header=''))))

django/http/response.py:HttpResponseBase

self.cookies = SimpleCookie()
self.cookies[key] = value

1.2 Bottle

使用

import bottle
from bottle import template, Bottle, static_file, request, redirect

bottle.TEMPLATE_PATH.append("./templates/")  # 指定模板目录

root = Bottle()

@root.route("/index", method=["GET", "POST"])#method 默认 GET, 可以指定其他请求或者请求方式列表
def index():
    print (request.method)     # POST
    print (request.forms)      # post 请求信息
    print (request.query)      # get 请求数据
    print (request.body)       # POST 请求数据
    print (request.files)      # 上传的文件信息
    print (request.cookies)    # cookie 信息
    print (request.environ)    # 环境信息
    print (request.json)  #
    print (request.params)  #
    if request.method == "GET":
        return template("<h1> Hello {{ name }}</h1>", name="Bottle")
    elif request.method == "POST":
        return redirect("/index/")

@root.route("/static/<path:path>")
def callback(path):
    return static_file(path, "static") # 指定静态文件目录 static


root.run(host="localhost", port=8080)

Bottle 获取 cookie 时,是通过官方库 Cookie(Python 2.7 自带) 中 SimpleCookie 封装,然后再解析为 dict

2 分析

Cookie 是取的 environ["HTTP_COOKIE"] ,这个值是个 String ,很多框架获取 cookie 都是在 request 类中进行实现的

3 实现

Butterfly 解析 Cookie 时也是放到了 request 类中实现,此处借鉴了 Django 的实现,不过解析到的 cookie item 中,如果 item 没有 "=" , 则会过滤掉

req.cookies()

响应首部 Set-Cookie 被用来由服务器端向客户端发送 cookie

Python 2.7 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
>>> C.values()
[<Morsel: fig='newton'>, <Morsel: sugar='wafer'>]
#------------------------------------------------------------------------------------
>>> header_list = []                                   # 添加到 HTTP headers list
>>> for c in C.values():
...    header_list.append(('Set-Cookie', c.OutputString()))
...
>>> header_list
[('Set-Cookie', 'fig=newton'), ('Set-Cookie', 'sugar=wafer')]
#------------------------------------------------------------------------------------
>>> C["sugar"].keys()
['comment', 'domain', 'secure', 'expires', 'max-age', 'version', 'path', 'httponly']
>>> C["sugar"].values()
['', '', '', '', '', '', '', '']

标准的 Set-Cookie Header:

Set-Cookie: key=value; path=path; domain=domain; max-age=max-age-in-seconds; expires=date-in-GMTString-format; secure; httponly

Cookies 可选属性

comment  :
domain   : cookie 的有效域 (有些网站有许多小的域名,例如百度可能还在"news.baidu.com" "zhidao.baidu.com" 和"v.baidu.com" 域名下有网页.如果想让"baidu.com"下的所有机器都可以读取该 cookie,必须在 cookie 中加入 "domain=.baidu.com")
secure   :
expires  : cookie 的生存周期
max-age  :
version  :
path     : cookie 的有效路径
httponly :

Last updated