路由参数
FastAPI 允许开发者通过简洁的Python语法声明路径参数,实现动态路由及参数处理。
基础概念
-
• 路径参数:路径中包含的动态部分,用花括号
{}
包裹,如/items/{item_id}
中的item_id
。 -
• 示例: 路径
/items/123
将传递参数item_id
值为123
。
声明路径参数
@app.get("/items/{item_id}") async def read_item(item_id): # item_id 为路径的参数 return {"item_id": item_id}
访问 http://127.0.0.1:8000/items/foo
,响应为 {"item_id": "foo"}
。
类型标注与数据转换
使用标准的 Python 类型标注为函数中的路径参数声明类型,并且自动转换标注的数据类型。
-
• 声明
@应用名称.请求方式("路径/{参数}") async def 函数名(参数名:类型): return 返回数据
-
• 示例
@app.get("/items/{item_id}") async def read_item(item_id: int): return {"item_id": item_id}
• 访问 http://127.0.0.1:8000/items/3
,响应为 {"item_id": 3}
,自动将字符串 “3” 转换为整型。
• 访问 http://127.0.0.1:8000/items/foo
,则返回错误信息,因为 “foo” 不能转换为整数。
• 类型
-
- 基本类型:
-
•
int
: 整数类型,如item_id: int
,会自动将路径中的字符串转换为整数。 -
•
float
: 浮点数类型,同理,会转换字符串到浮点数。 -
•
str
: 字符串类型,这是默认类型,通常不需要显式声明,但可以用于明确意图。 -
•
bool
: 布尔类型,虽然不常用作路径参数,但在某些场景下可能有其用途。
-
- 复合类型:
-
•
List[类型]
或Sequence[类型]
: 允许参数为一个列表或序列,如tags: List[str]
表示多个标签。 -
•
Dict[str, 类型]
或Mapping[str, 类型]
: 接受字典作为参数,键通常是字符串。 -
•
Union[类型1, 类型2, ...]
: 表示参数可以是多个类型中的任意一种。
-
- 自定义类型:
-
• Pydantic模型: 可以定义Pydantic模型作为路径参数类型,用于复杂的数据结构验证,如
user: UserInPath
,其中UserInPath
是一个Pydantic模型。 -
• Enum类型: 如上文所述,使用枚举(Enum)来限制路径参数的取值范围,提供额外的验证和清晰性。
-
- 特殊类型转换器:
- • 路径转换器(如
path
)可以用于处理路径中包含斜杠的特殊参数,例如file_path: Path
使用path
转换器。
-
- 可选参数与默认值:
-
• 使用默认值(如
item_id: int = None
)可以标记路径参数为可选,尽管这在路径参数中较少见,因为路径通常要求所有组件都是必需的。
-
• 类型示例
-
• 整数类型 (int)当路径中需要接收整数参数时,可以直接声明
int
类型。from fastapi import FastAPI app = FastAPI() @app.get("/items/{item_id}") async def read_item(item_id: int): return {"item_id": item_id}
访问
http://127.0.0.1:8000/items/42
,预期响应为{"item_id": 42}
。 -
• 浮点数类型 (float)若路径参数为浮点数,则声明为
float
类型。@app.get("/prices/{price}") async def show_price(price: float): return {"price": price}
访问
http://127.0.0.1:8000/prices/49.99
,预期响应为{"price": 49.99}
。 -
• 字符串类型 (str)字符串类型的路径参数是最常见的。
@app.get("/users/{username}") async def read_user(username: str): return {"username": username}
访问
http://127.0.0.1:8000/users/john_doe
,预期响应为{"username": "john_doe"}
。 -
• 布尔类型 (bool)虽然不常见,但路径参数也可以是布尔类型。
@app.get("/features/{feature_enabled}") async def feature_status(feature_enabled: bool): return {"feature_enabled": feature_enabled}
访问
http://127.0.0.1:8000/features/true
或http://127.0.0.1:8000/features/false
,预期响应分别为{"feature_enabled": true}
和{"feature_enabled": false}
。 -
• 复合类型示例
-
• 列表类型 (List[int])列表类型通常不直接用作路径参数,但可以这样声明。
from typing import List @app.get("/items/{item_ids}") async def read_items(item_ids: List[int]): return {"item_ids": item_ids}
-
• 字典类型 (Dict[str, str])字典类型同样少见,但可以展示类型标注的灵活性。
from typing import Dict @app.get("/config/{settings}") async def read_config(settings: Dict[str, str]): return {"settings": settings}
-
• 自定义类型示例
-
• Pydantic模型
-
Pydantic模型用于更复杂的请求处理和验证。
from pydantic import BaseModel from typing import Optional class Item(BaseModel): name: str description: str @app.get("/items/{item_id}") async def read_item(item_id: int, q: Optional[str] = None): item = {"item_id": item_id} if q: item.update({"q": q}) return item
-
• 枚举类型 (Enum)
-
枚举类型确保参数值只能是预定义选项之一。
from enum import Enum class ModelName(str, Enum): alexnet = "alexnet" resnet = "resnet" lenet = "lenet" @app.get("/models/{model_name}") async def get_model(model_name: ModelName): return {"model_name": model_name.value}
访问
http://127.0.0.1:8000/models/resnet
,预期响应为{"model_name": "resnet"}
。 -
可以通过
ModelName.lenet.value
来获取值"lenet"
。
数据校验
FastAPI 内置了强大的数据校验机制,能够确保传入的路径参数、查询参数、请求体等符合预期的类型。以下是一个使用 FastAPI 进行数据校验的例子:
整数类型校验 (int)
当你在路径操作中声明一个整数类型的参数时,FastAPI 会自动校验传入的值是否为有效的整数。
@app.get("/items/{item_id}") async def read_item(item_id: int): return {"item_id": item_id}
如果你尝试使用非整数值访问此路径,例如访问 http://127.0.0.1:8000/items/foo
,FastAPI 会返回一个清晰的错误响应:
{ "detail": [ { "type": "int_parsing", "loc": [ "path", "item_id" ], "msg": "Input should be a valid integer, unable to parse string as an integer", "input": "foo", "url": "https://errors.pydantic.dev/2.5/v/int_parsing" } ] }
这个错误响应指出了问题所在:item_id
应该是一个整数,但是接收到了字符串 “foo”。
浮点数类型校验 (float)
FastAPI 对浮点数类型的校验也同样严格。如果你声明的参数类型为 float
,那么即使传入的是数值,但如果是整数,也会被认为不符合类型要求。
例如,对于以下路径操作:
@app.get("/items/{item_id}") async def read_item(item_id: float): return {"item_id": item_id}
访问 http://127.0.0.1:8000/items/4.2
是有效的,因为 “4.2” 可以被解析为浮点数。但是,如果访问 http://127.0.0.1:8000/items/4
,即使 “4” 是一个数值,它也不是一个浮点数,因此会触发一个类型错误。
错误信息
FastAPI 提供的错误信息非常有助于调试。错误详细信息包括:
-
•
loc
:错误发生的具体位置,例如路径参数["path","item_id"]
-
•
msg
:错误的描述信息,例如"Input should be a valid integer"
。 -
•
type
:错误的类型,例如"int_parsing"
。
这些信息可以帮助开发者快速定位问题并采取相应的措施进行修复。
路径的路径参数
-
• 实现路径参数包含多级路径的情况,如处理
/files/home/johndoe/myfile.txt
请求。 -
• 利用路径转换器处理特殊字符,如路径分隔符
/
。
技巧介绍
-
- **路径参数声明:**这里的
{file_path:path}
表明file_path
能够匹配任何级别的目录结构。
- **路径参数声明:**这里的
-
• 使用
:path
转换器来指示路径参数可以包含任意路径结构。/files/{file_path:path}
-
- **路径操作函数定义:**参数
file_path
会接收完整的路径字符串,如home/johndoe/myfile.txt
。
- **路径操作函数定义:**参数
-
• 在路径操作函数中,通过类型注解定义路径参数。
@app.get("/files/{file_path:path}") async def read_file(file_path: str): return {"file_path": file_path}
-
- **处理斜杠开头路径:**FastAPI内部处理时会正确解析,不会影响参数值。
-
• 若文件路径以斜杠开头(如
/home/johndoe/myfile.txt
),URL中会展现为双斜杠序列(//
)。/files//home/johndoe/myfile.txt
启动
在FastAPI应用中,通常使用Uvicorn作为ASGI服务器来运行应用程序。
# 如果当前模块是主模块(直接运行而非导入) if __name__ == "__main__": # 导入uvicorn模块 import uvicorn # 使用uvicorn.run方法启动FastAPI应用 # 参数说明: # - app:要运行的FastAPI应用实例 # - host:监听的IP地址,默认为'127.0.0.1',这里显式指定为本地环回地址 # - port:监听的端口号,默认为8000,这里同样明确指定 # - reload:是否启用自动重载,默认为False,在开发模式下设置为True可以让修改后的代码立即生效,无需重启服务器 uvicorn.run(app, host="127.0.0.1", port=8000, reload=True)
当然,除了基本的host
, port
, 和 reload
参数外,uvicorn.run()
还支持一些其他常用的配置选项,这些选项帮助你更细致地控制Uvicorn服务器的行为。以下是几个重要参数的简要说明:
-
log_level
: 控制日志级别,可选值包括"debug"
,"info"
,"warning"
,"error"
,"critical"
。默认值通常是"info"
,在开发过程中,你可能希望设置为"debug"
以获得更详细的日志输出。
-
workers
: 指定要启动的工作进程数量,这对于提高并发处理能力特别有用。在多核CPU环境下,增加工作进程数可以显著提升应用性能。默认情况下,Uvicorn会根据环境自动选择合适的工作者数量,但在某些场景下,你可能需要手动指定。
-
access_log
: 一个布尔值,决定是否记录HTTP访问日志。默认为True
,如果你不希望记录这些日志(比如在生产环境中出于性能考虑),可以设置为False
。
-
timeout_keep_alive
: 定义空闲连接在关闭前保持活动的秒数。默认值是5秒,根据你的应用特性,你可能需要调整这个值。
-
proxy_headers
: 是否信任X-Forwarded-*头部信息,这对于在反向代理(如Nginx)后运行应用非常重要。设置为True
会允许Uvicorn根据这些头信息正确解析客户端的真实IP地址等信息。
-
root_path
: 如果你的应用部署在子路径下,可以通过这个参数指定根路径,这样路由也能正确解析。
-
limit_concurrency
: 限制同时处理的请求的最大数量,有助于防止服务过载。
-
limit_max_requests
: 设置每个工作进程在被重启前能处理的最大请求数量,有助于防止内存泄漏等问题。
示例代码,包含更多参数的使用:
# 使用uvicorn启动FastAPI应用,详细配置如下: uvicorn.run( # FastAPI应用实例 app, # 监听的IP地址,这里设置为本地环回地址,局域网内访问写”0.0.0.0“ host="127.0.0.1", # 监听的端口号 port=8000, # 开启自动重载,开发时非常有用,代码改动将自动重启服务器 reload=True, # 设置日志级别为debug,便于开发时查看详细日志信息 log_level="debug", # 启动的工作进程数,这里设置为2,适合多核CPU环境提高并发处理能力 workers=2, # 关闭访问日志记录,减少日志输出噪音,根据需要可开启 access_log=False, # 保持活动连接超时时间,单位秒,此处设置为10秒后关闭无活动连接 timeout_keep_alive=10, # 启用代理头部信任,当应用位于反向代理后方时,用于正确解析客户端信息 proxy_headers=True, # 指定应用部署的根路径,如果应用不是部署在域名根部,需设置此值,如"/my-app" root_path="/my-app", # 限制最大并发请求数,防止服务过载,根据服务器性能合理设定,这里设为100 limit_concurrency=100, # 工作进程处理的最大请求数量到达此值后将重启,有助于防止内存泄漏,设为5000 limit_max_requests=5000 )
通过这些参数,你可以根据实际部署环境和应用需求,微调Uvicorn服务器的配置,达到最佳的性能和管理效果。
为了帮助大家更好的学习网络安全,我给大家准备了一份网络安全入门/进阶学习资料,里面的内容都是适合零基础小白的笔记和资料,不懂编程也能听懂、看懂这些资料!
因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取
CSDN大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享
因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取