FastAPI Cookie 参数详解:用 Cookie 声明、验证与读取 HTTP Cookie
2026/9/7 2:02:58 网站建设 项目流程

FastAPI Cookie 参数详解:用 Cookie 声明、验证与读取 HTTP Cookie

【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi

本文基于 FastAPI 官方教程文档 cookie-params(德语版,对应英文版为 docs/en/docs/tutorial/cookie-params.md)展开。FastAPI 允许像声明QueryPath参数一样声明 Cookie 参数:只需从fastapi导入Cookie,用相同的方式设置默认值、附加验证与标注参数,即可从请求 Cookie 中按名称提取并自动完成类型转换与校验。读完本文,你将掌握 Cookie 参数的声明写法、Cookie在框架中的类层级关系,以及为什么必须显式使用Cookie才能避免参数被误判为 Query 参数,并理解 Cookie 值在依赖解析阶段的底层提取流程。

1. 导入Cookie

使用 Cookie 参数前,第一步是从fastapi中导入Cookie。官方示例文件 docs_src/cookie_params/tutorial001_an_py310.py 的完整代码如下:

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}

其中关键的第 3 行from fastapi import Cookie, FastAPI即文档强调的导入步骤。CookieQueryPath一样,是 FastAPI 顶层命名空间直接暴露的 API。

2. 声明 Cookie 参数

声明 Cookie 参数使用与PathQuery完全相同的结构:你可以为参数定义默认值,以及所有的额外验证或标注参数。

2.1 现代推荐写法(Annotated风格)

@app.get("/items/") async def read_items(ads_id: Annotated[str | None, Cookie()] = None): return {"ads_id": ads_id}

逐行解读:

  • Annotated[str | None, Cookie()]:第一个元素str | None声明参数类型——字符串或None;第二个元素Cookie()把该参数从默认的"Query 参数"语义转换为"从 Cookie 中提取"。
  • = None:指定默认值。当请求中没有名为ads_id的 Cookie 时,参数值为None
  • 由于参数类型包含None,该 Cookie 是可选的;如果你声明为Annotated[str, Cookie()](不可为空),FastAPI 会在缺少该 Cookie 时返回验证错误。

2.2 传统写法(旧风格)

仓库中同时提供了旧风格示例 docs_src/cookie_params/tutorial001_py310.py:

from fastapi import Cookie, FastAPI app = FastAPI() @app.get("/items/") async def read_items(ads_id: str | None = Cookie(default=None)): return {"ads_id": ads_id}

这里Cookie(default=None)Cookie当作一个"参数工厂"直接用作默认值。两种写法最终生成同样的路由行为,官方文档与当前示例主推Annotated风格。

2.3 可附带的验证与标注参数

CookieQueryPath共用同一套参数选项,因此声明 Cookie 时同样可以使用:

  • 元数据:titledescriptiondeprecatedexamples/openapi_examplesinclude_in_schema等(影响/docs中生成的 OpenAPI 文档);
  • 验证约束:gtgeltle(数值比较)、min_lengthmax_lengthpattern(字符串正则)、strictmultiple_ofallow_inf_nan等;
  • 别名:aliasvalidation_aliasserialization_alias,用于 Cookie 名称与 Python 变量名不一致(例如 Cookie 名与 Python 保留字冲突)的场景。

这些选项的完整签名可以在 fastapi/params.py 的Param基类与各参数类构造器中查证。

3. 技术细节:CookiePathQuery的"姐妹"类

官方文档特别指出:

CookiePathQuery的一个"姐妹"(sister)类。它也继承自同一个共同的Param类。

但请记住,当你从fastapi导入QueryPathCookie等对象时,它们实际上是函数,会返回特殊的

仓库源码完整印证了这两句话:

  1. 共同的Param基类。在 fastapi/params.py 中:

    class Cookie(Param): # type: ignore[misc] in_ = ParamTypes.cookie

    Cookie直接继承Param,并仅通过类属性in_ = ParamTypes.cookie声明自己的取值来源是 Cookie。这正是它与Queryin_ = ParamTypes.query)、Pathin_ = ParamTypes.path)成为"姐妹"类的机制——同一个基类、同一套验证参数,仅取值位置不同。

  2. 顶层名字是"返回类的函数"。在 fastapi/param_functions.py 中,Cookie被定义为一个带大量Doc文档标注的函数(第 1018 行def Cookie(...)),与同文件的Path(第 13 行)、Query(第 357 行)结构一致:从源码结构看,这些函数接收defaultaliastitledescription、各类验证约束等参数,并转发给params模块中对应的真实类(例如Path函数返回params.Path实例,Query函数返回params.Query实例,Cookie同理返回params.Cookie实例)。这种"函数 + 类"双层设计让 FastAPI 既能在Annotated中作为标注使用,又能在旧风格中作为"默认值"使用,同时把参数文档与 OpenAPI 生成所需信息集中维护在param_functions.py中。

4. 为什么必须用Cookie显式声明

文档给出了一条关键提示:

要声明 Cookie,你必须使用Cookie,否则这些参数会被解释为 Query 参数。

这一点在依赖解析源码中有直接证据。fastapi/dependencies/utils.py 在处理非 Body 参数时,会根据Param实例的in_归属把字段分派到不同的参数列表,并做了严格断言:

assert field_info_in == params.ParamTypes.cookie, ( f"non-body parameters must be in path, query, header or cookie: {field.name}" ) dependant.cookie_params.append(field)

也就是说:

  • 没有标注任何Param的简单类型参数(如裸的ads_id: str)会被归类为Query 参数,框架会去 URL 查询串里找?ads_id=...,而不是读 Cookie;
  • 只有标注了Cookie(其in_ParamTypes.cookie)的参数才会进入dependant.cookie_params列表,后续才从request.cookies中提取。

这正是文档强调"必须显式使用Cookie"的底层原因。

5. 注意:浏览器 Cookie 的特殊性与/docs界面限制

文档还提醒了一个容易被忽略的行为限制:

请记住,浏览器以特殊方式、在幕后处理 Cookie,并且不允许JavaScript随意地直接访问/修改它们。

当你访问/docsAPI 文档界面时,可以看到路径操作中 Cookie 的文档;但即使你填写了数据并点击"Execute",由于文档界面是基于JavaScript运行的,Cookie 并不会被发送,你会看到一条错误信息,仿佛你没有填写任何值。

也就是说:

  1. /docs(Swagger UI)能正确展示 Cookie 参数的 OpenAPI 定义(参数位于cookie位置);
  2. 但 Swagger UI 通过浏览器fetch发请求时无法可靠地注入自定义 Cookie,点击 Execute 后服务端读不到该 Cookie,若参数必填则返回 422 验证错误,看起来就像"没有填值"。

这是浏览器 Cookie 机制(而非 FastAPI)造成的限制。实际测试 Cookie 参数时,建议使用curl、Postman 等可直接控制Cookie请求头的工具,或框架自带的TestClient(见下一节)。

6. 底层原理:Cookie 值是如何被提取的

结合 fastapi/dependencies/utils.py,完整解析流程可以概括为:

  1. 收集阶段:路由参数被解析后,所有in_cookie的字段被归入dependant.cookie_params(同文件第 173 行初始化cookie_params: list[ModelField],并在第 189-195 行完成依赖树的扁平化收集)。

  2. 提取阶段:在生成请求参数值时,框架调用:

    cookie_values, cookie_errors = request_params_to_args( dependant.cookie_params, request.cookies ) values.update(cookie_values) errors += path_errors + query_errors + header_errors + cookie_errors

    即把 ASGI/Starlette 解析好的request.cookies字典(键为 Cookie 名,值为字符串)交给request_params_to_args,按字段定义完成取值、类型转换与验证;任何验证失败都会汇入errors,最终触发 422 响应。

  3. 类型转换:Cookie 值本质都是字符串,FastAPI 依据你声明的类型(如strint)自动转换;转换或验证失败时,与 Query/Path 参数一样返回统一的验证错误结构。

从源码结构看,Cookie 参数的处理路径与 Query/Header 参数共用同一套request_params_to_args工具函数,只是数据源不同(Query 来自request.query_params,Cookie 来自request.cookies),这也解释了为什么Cookie能完整复用Query的全部验证与元数据参数。

7. 测试验证

官方为该教程配置了对应的测试 tests/test_tutorial/test_cookie_params/test_tutorial001.py,其参数化用例覆盖了三种典型场景:

  • 请求携带{"ads_id": "ads_track", "session": "cookiesession"}两个 Cookie 访问/items,期望返回200且响应为{"ads_id": "ads_track"}
  • 请求只携带{"session": "cookiesession"}(无ads_id)访问/items,由于参数有默认值None,期望返回200且响应为{"ads_id": None}
  • 测试同时断言生成的 OpenAPI 中该参数的位置为"in": "cookie",验证文档元数据正确。

测试通过TestClient(mod.app, cookies=cookies)以字典形式注入 Cookie,这也是本地验证 Cookie 参数最直接的方式。

8. 小结

  • 声明 Cookie 使用Cookie,模式与QueryPath完全一致:Annotated[str | None, Cookie()] = None或旧风格ads_id: str | None = Cookie(default=None)
  • Cookie在 fastapi/params.py 中继承共同的Param基类,仅以in_ = ParamTypes.cookie标识取值来源;而从fastapi导入的Query/Path/Cookie等名字实际是 fastapi/param_functions.py 中返回特殊类实例的函数;
  • 必须显式标注Cookie,否则参数会被当作 Query 参数处理(见 fastapi/dependencies/utils.py 的分派与断言逻辑);
  • 运行时 Cookie 值从request.cookies提取并经request_params_to_args完成验证(见 fastapi/dependencies/utils.py);
  • 浏览器 JavaScript 无法随意操纵 Cookie,因此/docs界面中点击 Execute 不会真正发送 Cookie,集成测试请改用TestClient或外部 HTTP 客户端。

【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询