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 其他框架使用 Cookie
1.1 Django
使用
Django 中 cookie 的保存和存取
保存 cookie: 通过 HttpResponse 类的对象的 set_cookie 方法保存
response.set_cookie('键', '值',max_age)
读取 cookie:通过 HttpRequest 请求对象的 COOKIES 属性(字典类型)读取
request.COOKIES['键']
# 或者:
request.COOKIES.get('键')
获取 cookie
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 是获取到 cookie 字符串,然后将字符串解析为 Dict,不过 Django 在解析时,如果只指定了一个属性,则假定而不是,详情如下
https://bugzilla.mozilla.org/show_bug.cgi?id=169091
设置 cookie
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 实现
3.1 服务端获取客户端的 Cookie
Butterfly 解析 Cookie 时也是放到了 request 类中实现,此处借鉴了 Django 的实现,不过解析到的 cookie item 中,如果 item 没有 "=" , 则会过滤掉
3.2 服务器端向客户端发送 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