官方文档:Cookie 参数 - FastAPI
Cookie 参数¶
定义 Cookie
参数与定义 Query
和 Path
参数一样。
源码:
from typing import Annotated
from fastapi import Cookie, FastAPI
app = FastAPI()
@app.get("/items/")
async def read_items(ads_id: Annotated[str | None, Cookie()] = None):
return {"ads_id": ads_id}
导入 Cookie
¶
首先,导入 Cookie
:
from fastapi import Cookie, FastAPI
声明 Cookie
参数¶
声明 Cookie
参数的方式与声明 Query
和 Path
参数相同。第一个值是默认值,还可以传递所有验证参数或注释参数:
async def read_items(ads_id: Annotated[str | None, Cookie()] = None):
"技术细节"
Cookie
、Path
、Query
是兄弟类,都继承自共用的Param
类。注意,从
fastapi
导入的Query
、Path
、Cookie
等对象,实际上是返回特殊类的函数。
"说明"
必须使用
Cookie
声明 cookie 参数,否则该参数会被解释为查询参数。
小结¶
使用 Cookie
声明 cookie 参数的方式与 Query
和 Path
相同。
Cookie参数模型
如果你有一组相关的Cookie,你可以创建一个Pydantic模型来声明它们。🍪
这将允许您在多个地方重用模型,并一次声明所有参数的验证和元数据。😎
注:
自FastAPI 0.115.0版本起支持此功能。🤓
小贴士
同样的技术也适用于Query、Cookie和Header。😎
具有Pydantic模型的Cookie
在Pydantic模型中声明所需的cookie参数,然后将该参数声明为cookie:
from typing import Annotated
from fastapi import Cookie, FastAPI
from pydantic import BaseModel
app = FastAPI()
class Cookies(BaseModel):
session_id: str
fatebook_tracker: str | None = None
googall_tracker: str | None = None
@app.get("/items/")
async def read_items(cookies: Annotated[Cookies, Cookie()]):
return cookies
查看文档
您可以在/docs的文档UI中看到已定义的Cookie:
资讯
请记住,由于浏览器在幕后以特殊方式处理Cookie,因此它们不容易让JavaScript接触到它们。
如果您访问/docs上的API docs UI,您将能够看到路径操作的Cookie文档。
但是,即使您填写数据并单击“执行”,由于文档UI使用JavaScript,Cookie也不会被发送,您将看到一条错误消息,就像您没有写入任何值一样。
禁止额外Cookie
在某些特殊情况下(可能不是很常见),您可能希望限制您想要接收的Cookie。
您的API现在有权控制自己的cookie同意。🤪🍪
您可以使用Pydantic的模型配置来禁止任何额外的字段:
from typing import Annotated, Union
from fastapi import Cookie, FastAPI
from pydantic import BaseModel
app = FastAPI()
class Cookies(BaseModel):
model_config = {"extra": "forbid"}
session_id: str
fatebook_tracker: Union[str, None] = None
googall_tracker: Union[str, None] = None
@app.get("/items/")
async def read_items(cookies: Annotated[Cookies, Cookie()]):
return cookies
如果客户端尝试发送一些额外的Cookie,他们将收到错误响应。
可怜的cookie横幅,他们竭尽全力让API同意拒绝它。🍪
例如,如果客户端尝试发送一个值为good-list please的santa_tracker cookie,客户端将收到一个错误响应,告诉他们不允许使用santa_track cookie:
{ "detail": [ { "type": "extra_forbidden", "loc": ["cookie", "santa_tracker"], "msg": "Extra inputs are not permitted", "input": "good-list-please", } ] }
摘要
您可以使用Pydantic模型在FastAPI中声明Cookie。😎
实践
又碰到问题了,这里是获得cookie,那么应该怎么来实践检验一下呢? 我认为需要先想办法把cookie存进去才行。
在测试中用浏览器发送cookie进去有点麻烦,需要按F12然后进行一些操作,那么问题就变成:
应该怎么用curl来发送带有cookie的请求?
后来发现curl可以用-b参数带cookie,如:
curl -X GET "http://127.0.0.1:8000/items/" -b "ads_id=12345" -b "another_cookie=67890"
curl -X GET "http://127.0.0.1:8000/items/" -b "session_id=abc123;fatebook_tracker=fb_track_123;googall_tracker=ga_track_456"
FastAPI cookie源码
将代码存为cookie.py文件
from typing import Annotated
from fastapi import Cookie, FastAPI
from pydantic import BaseModel
app = FastAPI()
class Cookies(BaseModel):
# 禁止其它cookie
model_config = {"extra": "forbid"}
session_id: str
fatebook_tracker: str | None = None
googall_tracker: str | None = None
@app.get("/items/")
async def read_items(cookies: Annotated[Cookies, Cookie()]):
return cookies
启动服务
uvicorn cookie:app --reload
curl 进行cookie测试
执行curl命令和输出:
curl -X GET "http://127.0.0.1:8000/items/" -b "session_id=abc123;fatebook_tracker=fb_track_123;googall_tracker=ga_track_456"
{"session_id":"abc123","fatebook_tracker":"fb_track_123","googall_tracker":"ga_track_456"}
测试通过!
禁止额外cookie
代码写入cookie.py文件:
from typing import Annotated
from fastapi import Cookie, FastAPI
from pydantic import BaseModel
app = FastAPI()
class Cookies(BaseModel):
# 禁止其它cookie
model_config = {"extra": "forbid"}
session_id: str
fatebook_tracker: str | None = None
googall_tracker: str | None = None
@app.get("/items/")
async def read_items(cookies: Annotated[Cookies, Cookie()]):
return cookies
启动服务
uvicorn cookie:app --reload
curl 进行cookie测试
如果有超过设置的cookie,会报错
curl -X GET "htt.0.1:8000/items/" -b "session_id=abc123;test=test;fatebook_tracker=fb_track_123;googall_tracker=ga_track_456;temp=test"
{"detail":[{"type":"extra_forbidden","loc":["cookie","test"],"msg":"Extra inputs are not permitted","input":"test"},{"type":"extra_forbidden","loc":["cookie","temp"],"msg":"Extra inputs are not permitted","input":"test"}]}
如果直接用chromium浏览器浏览:http://127.0.0.1:8000/items/
因为浏览器会自动放一些cookie,所以也会报错:
{"detail":[{"type":"missing","loc":["cookie","session_id"],"msg":"Field required","input":{"CSRF-Token-5QWX4YR":"qThiWAbkWwNwXTA624FM3XUWZYkCujme","sessionid-5QWX4YR":"rhumGzAQQv9SmQobMdYcQKZgNpNFMgnK"}},{"type":"extra_forbidden","loc":["cookie","CSRF-Token-5QWX4YR"],"msg":"Extra inputs are not permitted","input":"qThiWAbkWwNwXTA624FM3XUWZYkCujme"},{"type":"extra_forbidden","loc":["cookie","sessionid-5QWX4YR"],"msg":"Extra inputs are not permitted","input":"rhumGzAQQv9SmQobMdYcQKZgNpNFMgnK"}]}
总结
使用 Cookie
声明 cookie 参数的方式与 Query
和 Path
相同,写起来毫无压力!