# 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 其他框架使用 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

```python
@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
```

#### 设置 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

#### 使用

```python
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 没有 "=" , 则会过滤掉

```
req.cookies()
```

### 3.2 服务器端向客户端发送 Cookie

响应首部 [Set-Cookie](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Set-Cookie) 被用来由服务器端向客户端发送 cookie

[Python 2.7 cookie 库](https://docs.python.org/2/library/cookie.html)

```python
>>> 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 :
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://meetbill.gitbook.io/butterfly-project-doc/project-framework/how/api/butterfly-cookie.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
