FastAPI 单元子单元
文章目录
一、FastAPI 核心类
功能概述
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,基于标准 Python 类型提示。它允许开发者快速构建、测试和部署 RESTful API 服务,同时提供自动化的交互式 API 文档。
常用功能块
-
路由定义:通过装饰器如
@app.get()
、@app.post()
等定义不同的 HTTP 方法对应的路由处理函数。- 示例:
from fastapi import FastAPI app = FastAPI() @app.get("/") async def read_root(): return {"message": "Hello World"}
-
参数解析:自动解析路径参数、查询参数、请求体等,支持复杂数据类型的验证和转换。
- 示例:
@app.get("/items/{item_id}") async def read_item(item_id: int, q: str = None): return {"item_id": item_id, "q": q}
-
依赖注入:通过
Depends
实现依赖项的注入,简化代码复用和模块化设计。- 示例:
from fastapi import Depends, FastAPI async def common_parameters(q: str = None, skip: int = 0, limit: int = 100): return {"q": q, "skip": skip, "limit": limit} app = FastAPI() @app.get("/items/") async def read_items(commons: dict = Depends(common_parameters)): return {"items": [{"item_id": "Foo"}], **commons}
-
中间件支持:可以添加中间件来处理跨域请求、请求日志记录等全局功能。
- 示例:
from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware app = FastAPI() app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], )
-
自动文档生成:内置了交互式的 API 文档,如 Swagger UI 和 ReDoc,方便开发者和调用者查看和测试 API。
- 示例:启动应用后访问
http://localhost:8000/docs
或http://localhost:8000/redoc
即可查看自动生成的文档。
- 示例:启动应用后访问
高阶使用功能块
-
自定义异常处理:可以定义自定义的异常处理器来处理特定的异常情况,返回统一的错误响应格式。
- 示例:
from fastapi import FastAPI, HTTPException, status from fastapi.exceptions import RequestValidationError from fastapi.responses import JSONResponse app = FastAPI() @app.exception_handler(HTTPException) async def http_exception_handler(request, exc): return JSONResponse( status_code=exc.status_code, content={"detail": exc.detail}, ) @app.exception_handler(RequestValidationError) async def validation_exception_handler(request, exc): return JSONResponse( status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, content={"detail": "Validation error"}, )
-
异步支持:充分利用 Python 的异步特性,提高并发处理能力,适合处理 I/O 密集型任务。
- 示例:
import asyncio from fastapi import FastAPI app = FastAPI() async def simulate_db_call(): await asyncio.sleep(1) return {"data": "result"} @app.get("/async-items/") async def get_async_items(): data = await simulate_db_call() return data
-
数据校验与转换:结合 Pydantic 模型,对请求体进行严格的校验和数据类型转换,确保数据的完整性和正确性。
- 示例:
from pydantic import BaseModel from fastapi import FastAPI, status app = FastAPI() class Item(BaseModel): name: str description: str = None price: float tax: float = None @app.post("/items/", status_code=status.HTTP_201_CREATED) async def create_item(item: Item): return item.dict()
-
支持 WebSocket:除了传统的 HTTP 请求,还支持 WebSocket 实时通信,适用于需要双向通信的场景,如聊天应用、实时数据推送等。
- 示例:
from fastapi import FastAPI, WebSocket app = FastAPI() @app.websocket("/ws") async def websocket_endpoint(websocket: WebSocket): await websocket.accept() while True: data = await websocket.receive_text() await websocket.send_text(f"Message text was: {data}")
-
插件生态系统:丰富的第三方插件支持,如数据库集成、认证授权、缓存等,可以快速扩展应用的功能。
- 示例:使用
fastapi-jwt-auth
插件实现 JWT 认证
from fastapi import FastAPI, Depends, HTTPException from fastapi_jwt_auth import AuthJWT from pydantic import BaseModel app = FastAPI() class Settings(BaseModel): authjwt_secret_key: str = "secret-key" @AuthJWT.load_config def get_config(): return Settings() @app.post("/login") async def login(user: dict, Authorize: AuthJWT = Depends()): if user.username != "test" or user.password != "test": raise HTTPException(status_code=401, detail="Bad username or password") access_token = Authorize.create_access_token(subject=user.username) return {"access_token": access_token} @app.get("/protected") async def protected(Authorize: AuthJWT = Depends()): Authorize.jwt_required() current_user = Authorize.get_jwt_subject() return {"user": current_user}
- 示例:使用
二、BackgroundTasks 背景任务
功能概述
BackgroundTasks 用于在处理 HTTP 请求或 WebSocket 连接时,执行一些耗时的后台任务,而不需要让客户端等待这些任务完成。这在发送邮件、处理日志、清理数据等场景中非常有用。
常用功能块
-
添加后台任务:通过将函数作为参数传递给
BackgroundTasks
,在请求处理完成后自动执行。- 示例:
from fastapi import BackgroundTasks, FastAPI app = FastAPI() def write_log(message: str): with open("log.txt", mode="a") as log_file: log_file.write(message + "\n") @app.post("/send-notification/") async def send_notification(email: str, background_tasks: BackgroundTasks): background_tasks.add_task(write_log, f"Notification sent to {email}") return {"message": "Notification sent in the background"}
-
传递参数给后台任务:可以向后台任务函数传递多个参数,包括从请求中获取的数据。
- 示例:
def process_data(data: dict, user_id: int): # 处理数据并保存到数据库等操作 pass @app.post("/process-data/") async def process_data_endpoint(data: dict, background_tasks: BackgroundTasks): user_id = 123 # 假设从请求中获取用户 ID background_tasks.add_task(process_data, data, user_id) return {"message": "Data processing started"}
-
后台任务的依赖注入:后台任务也可以使用依赖注入来获取所需的数据或服务。
- 示例:
from fastapi import Depends async def get_db(): db = DBConnection() try: yield db finally: db.close() def update_database(db: DBConnection, item_id: int): # 更新数据库操作 pass @app.put("/items/{item_id}") async def update_item( item_id: int, background_tasks: BackgroundTasks, db: DBConnection = Depends(get_db), ): background_tasks.add_task(update_database, db, item_id) return {"message": "Item update started"}
-
后台任务的异常处理:可以为后台任务定义异常处理逻辑,捕获任务执行过程中可能出现的错误。
- 示例:
def error_handler(func): def wrapper(*args, **kwargs): try: func(*args, **kwargs) except Exception as e: # 记录错误日志等操作 print(f"Error occurred: {e}") return wrapper @error_handler def risky_task(): # 可能会出错的任务 pass @app.post("/run-risky-task/") async def run_risky_task(background_tasks: BackgroundTasks): background_tasks.add_task(risky_task) return {"message": "Risky task started"}
-
后台任务的状态监控:通过一些机制(如数据库记录、消息队列等)监控后台任务的执行状态,以便后续查询或处理。
- 示例:
from datetime import datetime def record_task_status(task_id: str, status: str): # 将任务状态记录到数据库或其他存储中 pass def long_running_task(task_id: str): record_task_status(task_id, "started") # 执行长时间任务 record_task_status(task_id, "completed") @app.post("/start-task/") async def start_task(background_tasks: BackgroundTasks): task_id = str(uuid.uuid4()) background_tasks.add_task(long_running_task, task_id) record_task_status(task_id, "pending") return {"task_id": task_id, "message": "Task started"}
高阶使用功能块
-
后台任务的优先级控制:根据任务的重要性和紧急程度,设置不同的优先级,确保高优先级任务优先执行。
- 示例:
class PriorityBackgroundTasks: def __init__(self): self.tasks = [] def add_task(self, func, *args, priority=0, **kwargs): self.tasks.append((priority, func, args, kwargs)) self.tasks.sort(key=lambda x: x[0]) # 按优先级排序 async def run(self): while self.tasks: priority, func, args, kwargs = self.tasks.pop(0) await func(*args, **kwargs) priority_background_tasks = PriorityBackgroundTasks() async def high_priority_task(): # 高优先级任务 pass async def low_priority_task(): # 低优先级任务 pass @app.post("/run-priority-tasks/") async def run_priority_tasks(): priority_background_tasks.add_task(high_priority_task, priority=1) priority_background_tasks.add_task(low_priority_task, priority=2) await priority_background_tasks.run() return {"message": "Tasks started with priority"}
-
后台任务的分布式执行:在多服务器或容器环境下,将后台任务分布到不同的工作进程或机器上执行,提高任务处理的并发能力和可靠性。
- 示例:使用 Celery 实现分布式任务队列
from celery import Celery celery_app = Celery('tasks', broker='pyamqp://guest@localhost//') @celery_app.task def distributed_task(): # 分布式执行的任务 pass @app.post("/start-distributed-task/") async def start_distributed_task(): distributed_task.delay() return {"message": "Distributed task started"}
-
后台任务的进度跟踪与反馈:对于长时间运行的任务,向客户端提供任务进度的实时反馈,增强用户体验。
- 示例:通过 WebSocket 实时推送任务进度
from fastapi import WebSocket class TaskProgress: def __init__(self): self.progress = 0 self.websocket: WebSocket = None async def update_progress(self, progress: int): self.progress = progress if self.websocket: await self.websocket.send_text(f"Progress: {progress}%") async def run_task(self): for i in range(0, 101, 10): await self.update_progress(i) await asyncio.sleep(1) task_progress = TaskProgress() @app.websocket("/ws/progress") async def websocket_progress(websocket: WebSocket): await websocket.accept() task_progress.websocket = websocket await task_progress.run_task() await websocket.close() @app.get("/start-progress-task/") async def start_progress_task(): # 启动任务并关联 WebSocket return {"message": "Progress task started"}
-
后台任务的资源限制与隔离:对后台任务的资源使用(如内存、CPU、网络带宽等)进行限制和隔离,防止任务之间相互影响,保证系统的稳定性。
- 示例:使用 Docker 容器隔离任务
import docker def run_task_in_container(): client = docker.from_env() container = client.containers.run( "task-image", detach=True, mem_limit="128m", cpus=0.5 ) container.wait() container.remove() @app.post("/run-containerized-task/") async def run_containerized_task(background_tasks: BackgroundTasks): background_tasks.add_task(run_task_in_container) return {"message": "Containerized task started"}
-
后台任务的调度与计划:根据业务需求,定期或按照特定的时间计划执行后台任务,如定时备份数据、定时发送报告等。
- 示例:使用 APScheduler 实现任务调度
from apscheduler.schedulers.asyncio import AsyncIOScheduler scheduler = AsyncIOScheduler() @scheduler.scheduled_job('interval', minutes=1) async def scheduled_task(): # 每分钟执行一次的任务 pass scheduler.start() @app.on_event("startup") async def startup(): scheduler.start() @app.on_event("shutdown") async def shutdown(): scheduler.shutdown()
三、UploadFile 文件上传
功能概述
UploadFile 提供了对文件上传的处理能力,支持单文件和多文件上传,能够获取文件的内容、文件名、内容类型等信息,并方便地将文件保存到服务器或进行进一步的处理。
常用功能块
-
单文件上传:通过
File
参数接收上传的单个文件,并读取文件内容。- 示例:
from fastapi import FastAPI, File, UploadFile app = FastAPI() @app.post("/upload-file/") async def create_upload_file(file: UploadFile = File(...)): contents = await file.read() # 处理文件内容,如保存到服务器、上传到云存储等 return {"filename": file.filename, "content_type": file.content_type}
-
多文件上传:允许用户同时上传多个文件,并对每个文件进行处理。
- 示例:
@app.post("/upload-multiple-files/") async def create_multiple_upload_files(files: list[UploadFile] = File(...)): for file in files: contents = await file.read() # 处理每个文件 return {"filenames": [file.filename for file in files]}
-
文件保存到服务器:将上传的文件保存到服务器的指定目录。
- 示例:
import shutil from pathlib import Path @app.post("/upload-and-save-file/") async def upload_and_save_file(file: UploadFile = File(...)): save_dir = Path("uploads") save_dir.mkdir(exist_ok=True) save_path = save_dir / file.filename with open(save_path, "wb") as buffer: shutil.copyfileobj(file.file, buffer) return {"filename": file.filename, "save_path": str(save_path)}
-
文件类型验证:根据文件的扩展名或 MIME 类型,验证上传的文件是否符合要求。
- 示例:
ALLOWED_EXTENSIONS = {"txt", "pdf", "png", "jpg", "jpeg"} def allowed_file(filename: str): return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS @app.post("/upload-validated-file/") async def upload_validated_file(file: UploadFile = File(...)): if not allowed_file(file.filename): raise HTTPException(status_code=400, detail="Invalid file type") contents = await file.read() # 处理文件 return {"filename": file.filename}
-
大文件上传处理:对于大文件上传,可以设置文件大小限制,并采用分块读取的方式处理文件内容,避免内存溢出。
- 示例:
MAX_FILE_SIZE = 10 * 1024 * 1024 # 10MB @app.post("/upload-large-file/") async def upload_large_file(file: UploadFile = File(...)): file_size = 0 while True: chunk = await file.read(1024 * 1024) # 每次读取 1MB if not chunk: break file_size += len(chunk) if file_size > MAX_FILE_SIZE: raise HTTPException(status_code=413, detail="File too large") # 处理文件块 return {"filename": file.filename, "file_size": file_size}
高阶使用功能块
-
文件内容流式处理:对于需要实时处理的文件,如视频流、日志流等,采用流式读取和处理的方式,提高效率和响应速度。
- 示例:
from fastapi.responses import StreamingResponse @app.post("/stream-process-file/") async def stream_process_file(file: UploadFile = File(...)): async def process_chunk(): while True: chunk = await file.read(1024) if not chunk: break # 实时处理文件块,如分析视频帧、解析日志行等 yield chunk return StreamingResponse(process_chunk(), media_type="application/octet-stream")
-
文件上传的并发控制:限制同时上传的文件数量,防止服务器资源被过多占用。
- 示例:
from fastapi.concurrency import run_in_threadpool import asyncio MAX_CONCURRENT_UPLOADS = 3 semaphore = asyncio.Semaphore(MAX_CONCURRENT_UPLOADS) async def process_upload(file: UploadFile): async with semaphore: contents = await file.read() # 处理文件 return {"filename": file.filename} @app.post("/concurrent-upload/") async def concurrent_upload(files: list[UploadFile] = File(...)): tasks = [process_upload(file) for file in files] results = await asyncio.gather(*tasks) return results
-
文件上传的断点续传:支持大文件上传的断点续传功能,提高上传的可靠性和用户体验。
- 示例:使用范围请求头实现断点续传
from fastapi import Header @app.post("/resume-upload/") async def resume_upload( file: UploadFile = File(...), range: str = Header(None) ): if range: start, end = map(int, range.replace("bytes=", "").split("-")) file.file.seek(start) contents = await file.read(end - start + 1) # 处理文件片段并合并 return {"filename": file.filename, "range": range} else: # 普通上传 contents = await file.read() return {"filename": file.filename}
-
文件上传的安全增强:对上传的文件进行病毒扫描、内容过滤等安全检查,防止恶意文件上传。
- 示例:集成第三方病毒扫描工具
import clamd cd = clamd.ClamdUnixSocket() # 或使用网络套接字 @app.post("/secure-upload/") async def secure_upload(file: UploadFile = File(...)): contents = await file.read() scan_result = cd.scan_string(contents) if scan_result and scan_result['stream'][0] == 'OK': # 文件安全,进行处理 return {"filename": file.filename} else: raise HTTPException(status_code=400, detail="Virus detected")
-
文件上传的元数据处理:提取文件的元数据(如 EXIF 数据、PDF 元数据等),并进行相应的处理或存储。
- 示例:提取图片的 EXIF 数据
from PIL import Image from PIL.ExifTags import TAGS @app.post("/upload-with-exif/") async def upload_with_exif(file: UploadFile = File(...)): contents = await file.read() image = Image.open(io.BytesIO(contents)) exif_data = image._getexif() if exif_data: decoded_exif = {TAGS.get(tag_id): value for tag_id, value in exif_data.items()} # 处理 EXIF 数据,如记录拍摄时间、地点等 return {"filename": file.filename, "exif_data": decoded_exif}
四、HTTPException 和 WebSocketException 异常处理
功能概述
HTTPException 用于在处理 HTTP 请求时抛出异常,返回特定的 HTTP 状态码和错误信息。WebSocketException 则用于在 WebSocket 连接过程中处理异常情况,如关闭连接、发送错误消息等。
常用功能块
-
自定义 HTTP 错误响应:在需要返回特定错误信息时,抛出 HTTPException 并指定状态码和详情。
- 示例:
from fastapi import FastAPI, HTTPException app = FastAPI() @app.get("/items/{item_id}") async def read_item(item_id: int): if item_id < 0: raise HTTPException(status_code=400, detail="Item ID must be positive") return {"item_id": item_id}
-
WebSocket 异常处理:在 WebSocket 连接建立、接收消息或关闭过程中处理异常,确保连接的正常关闭和错误通知。
- 示例:
from fastapi import WebSocket, WebSocketException @app.websocket("/ws") async def websocket_endpoint(websocket: WebSocket): try: await websocket.accept() while True: data = await websocket.receive_text() if data == "error": raise WebSocketException(code=status.WS_1008_POLICY_VIOLATION, reason="Invalid message") await websocket.send_text(f"Message: {data}") except WebSocketException as e: await websocket.close(code=e.code, reason=e.reason)
-
全局异常处理器:定义全局的异常处理器,捕获所有未处理的异常并返回统一的错误响应格式。
- 示例:
from fastapi import FastAPI, status from fastapi.exceptions import RequestValidationError from fastapi.responses import JSONResponse app = FastAPI() @app.exception_handler(HTTPException) async def http_exception_handler(request, exc): return JSONResponse( status_code=exc.status_code, content={"detail": exc.detail}, ) @app.exception_handler(RequestValidationError) async def validation_exception_handler(request, exc): return JSONResponse( status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, content={"detail": "Validation error"}, )
-
异常处理的依赖注入:在异常处理过程中使用依赖注入获取所需的服务或数据。
- 示例:
from fastapi import Depends, HTTPException async def get_db(): db = DBConnection() try: yield db finally: db.close() @app.exception_handler(HTTPException) async def http_exception_handler(request, exc, db: DBConnection = Depends(get_db)): # 记录错误日志到数据库等操作 return JSONResponse( status_code=exc.status_code, content={"detail": exc.detail}, )
-
异常处理的扩展功能:根据不同的异常类型返回不同的响应格式,如 JSON、XML、HTML 等。
- 示例:根据 Accept 请求头返回不同的错误格式
from fastapi import Request @app.exception_handler(HTTPException) async def http_exception_handler(request: Request, exc): accept = request.headers.get("accept", "") if "application/json" in accept: return JSONResponse( status_code=exc.status_code, content={"detail": exc.detail}, ) elif "text/html" in accept: return HTMLResponse( status_code=exc.status_code, content=f"<html><body><h1>Error {exc.status_code}</h1><p>{exc.detail}</p></body></html>" ) else: return PlainTextResponse( status_code=exc.status_code, content=exc.detail )
高阶使用功能块
-
异常处理的中间件集成:将异常处理逻辑集成到中间件中,实现更灵活的错误处理和日志记录。
- 示例:
from fastapi import Request, Response from fastapi.middleware import Middleware class ExceptionMiddleware: async def __call__(self, request: Request, call_next): try: response = await call_next(request) return response except HTTPException as e: # 自定义错误处理逻辑 return JSONResponse( status_code=e.status_code, content={"detail": e.detail}, ) except Exception as e: # 捕获其他异常并记录日志 return JSONResponse( status_code=500, content={"detail": "Internal server error"}, ) app = FastAPI() app.add_middleware(ExceptionMiddleware)
-
分布式追踪与异常监控:结合分布式追踪系统和异常监控工具,记录异常发生的上下文信息,便于排查和分析问题。
- 示例:使用 Sentry 进行异常监控
import sentry_sdk from sentry_sdk.integrations.asgi import SentryAsgiMiddleware sentry_sdk.init( dsn="your_sentry_dsn", traces_sample_rate=1.0 ) app = FastAPI() app.add_middleware(SentryAsgiMiddleware) @app.exception_handler(HTTPException) async def http_exception_handler(request, exc): # 记录异常到 Sentry sentry_sdk.capture_exception(exc) return JSONResponse( status_code=exc.status_code, content={"detail": exc.detail}, )
-
异常处理的自动化测试:编写自动化测试用例,验证异常处理逻辑的正确性和一致性。
- 示例:使用 pytest 测试异常处理
from fastapi.testclient import TestClient client = TestClient(app) def test_http_exception(): response = client.get("/items/-1") assert response.status_code == 400 assert response.json() == {"detail": "Item ID must be positive"} def test_websocket_exception(): with client.websocket_connect("/ws") as websocket: websocket.send_text("error") response = websocket.receive() assert response["code"] == 1008 assert response["reason"] == "Invalid message"
-
异常处理的性能优化:对异常处理逻辑进行性能优化,减少不必要的计算和 I/O 操作,提高系统的响应速度。
- 示例:缓存常见的错误响应
from fastapi import FastAPI, HTTPException from fastapi.responses import JSONResponse error_cache = {} @app.exception_handler(HTTPException) async def http_exception_handler(request, exc): if exc.status_code in error_cache: return error_cache[exc.status_code] else: response = JSONResponse( status_code=exc.status_code, content={"detail": exc.detail}, ) error_cache[exc.status_code] = response return response
-
多语言异常处理支持:根据客户端的语言偏好返回不同语言的错误信息,提升国际化应用的用户体验。
- 示例:根据 Accept-Language 请求头返回多语言错误信息
from fastapi import Request error_messages = { 400: { "en": "Bad request", "zh": "请求错误" }, 404: { "en": "Not found", "zh": "未找到" } } @app.exception_handler(HTTPException) async def http_exception_handler(request: Request, exc): accept_language = request.headers.get("accept-language", "en") lang = accept_language.split(",")[0].split(";")[0] error_message = error_messages.get(exc.status_code, {}).get(lang, "Error") return JSONResponse( status_code=exc.status_code, content={"detail": error_message}, )
五、参数处理函数(Body、Cookie、Depends、File、Form、Header、Path、Query、Security)
功能概述
这些参数处理函数用于从不同的来源(如请求体、Cookie、查询参数、路径参数等)获取数据,并支持数据验证、依赖注入、安全认证等功能,使参数处理更加灵活和可靠。
常用功能块
-
Body:处理 JSON 请求体:从请求体中获取 JSON 格式的数据,并自动进行数据验证和转换。
- 示例:
from pydantic import BaseModel from fastapi import Body, FastAPI app = FastAPI() class Item(BaseModel): name: str description: str = None price: float tax: float = None @app.post("/items/") async def create_item(item: Item = Body(...)): return item.dict()
-
Cookie:获取 Cookie 值:从请求的 Cookie 中获取特定的值,支持默认值和数据验证。
- 示例:
from fastapi import Cookie, FastAPI app = FastAPI() @app.get("/items/") async def read_items(ads_id: str = Cookie(None)): return {"ads_id": ads_id}
-
Depends:依赖注入:将常见的参数或服务作为依赖项注入到路由处理函数中,减少代码重复。
- 示例:
from fastapi import Depends, FastAPI async def get_db(): db = DBConnection() try: yield db finally: db.close() app = FastAPI() @app.get("/items/") async def read_items(db: DBConnection = Depends(get_db)): # 使用 db 进行数据库操作 return {"items": [{"item_id": "Foo"}]}
-
File:处理文件上传:与 UploadFile 配合使用,声明文件上传参数。
- 示例:
from fastapi import File, UploadFile @app.post("/upload-file/") async def create_upload_file(file: UploadFile = File(...)): contents = await file.read() return {"filename": file.filename}
-
Form:处理表单数据:从表单提交的数据中获取字段值,支持多值和文件上传。
- 示例:
from fastapi import Form @app.post("/login/") async def login(username: str = Form(...), password: str = Form(...)): return {"username": username}
-
Header:获取请求头:从请求头中获取特定的值,支持自定义头和数据验证。
- 示例:
from fastapi import Header @app.get("/items/") async def read_items(user_agent: str = Header(None)): return {"User-Agent": user_agent}
-
Path:路径参数:从 URL 路径中获取参数值,支持参数校验和转换。
- 示例:
from fastapi import Path @app.get("/items/{item_id}") async def read_item(item_id: int = Path(..., gt=0)): return {"item_id": item_id}
-
Query:查询参数:从 URL 查询字符串中获取参数值,支持默认值、别名和数据验证。
- 示例:
from fastapi import Query @app.get("/items/") async def read_items(q: str = Query(None, min_length=3)): return {"q": q}
-
Security:安全认证:集成安全认证方案,如 OAuth2、API 密钥等,保护 API 资源。
- 示例:使用 OAuth2 密码流
from fastapi import Depends, Security from fastapi.security import OAuth2PasswordBearer oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") async def get_current_user(token: str = Depends(oauth2_scheme)): # 验证 token 并获取当前用户 return {"username": "test"} @app.get("/users/me") async def read_users_me(current_user: dict = Security(get_current_user)): return current_user
高阶使用功能块
-
组合参数处理:将多个参数处理函数组合使用,处理复杂的请求数据结构。
- 示例:同时处理 JSON 请求体、查询参数和路径参数
@app.post("/items/{item_id}") async def update_item( item_id: int = Path(..., gt=0), item: Item = Body(...), q: str = Query(None) ): return {"item_id": item_id, "item": item.dict(), "q": q}
-
自定义参数验证逻辑:通过定义 Pydantic 模型的验证方法或使用依赖项,实现自定义的参数验证逻辑。
- 示例:定义 Pydantic 模型的验证方法
from pydantic import BaseModel, validator class Item(BaseModel): name: str description: str = None price: float tax: float = None @validator("price") def price_must_be_positive(cls, v): if v <= 0: raise ValueError("Price must be positive") return v @app.post("/items/") async def create_item(item: Item = Body(...)): return item.dict()
-
参数处理的性能优化:对参数处理逻辑进行性能优化,如缓存验证结果、减少不必要的计算等。
- 示例:缓存路径参数的验证结果
from functools import lru_cache @lru_cache(maxsize=100) def validate_item_id(item_id: int): if item_id <= 0: raise ValueError("Item ID must be positive") return item_id @app.get("/items/{item_id}") async def read_item(item_id: int = Path(...)): validated_id = validate_item_id(item_id) return {"item_id": validated_id}
-
参数处理的国际化支持:根据客户端的语言偏好,对参数的错误信息进行多语言转换。
- 示例:使用 i18n 库实现参数验证的多语言支持
from fastapi import Request from pydantic import BaseModel from pydantic.i18n import Translator translator = Translator("zh") class Item(BaseModel): name: str class Config: error_msg_templates = { "value_error.missing": translator("field_required") } @app.post("/items/") async def create_item(item: Item = Body(...)): return item.dict()
-
参数处理的扩展功能:通过继承和扩展参数处理函数,实现特定的业务逻辑和功能。
- 示例:扩展 Body 参数处理函数以支持自定义的请求体格式
from fastapi.params import Body from fastapi import Request class CustomBody(Body): def __init__(self, default, *, media_type="application/json", **kwargs): super().__init__(default, media_type=media_type, **kwargs) async def get_value(self, name: str, request: Request): # 自定义获取请求体值的逻辑 body = await request.body() # 解析自定义格式的请求体 return parsed_value @app.post("/custom-items/") async def create_custom_item(item: Item = CustomBody(...)): return item.dict()
六、Request 和 Response 请求与响应
功能概述
Request 对象表示客户端发送的 HTTP 请求,提供了获取请求方法、URL、头、正文等信息的方法。Response 对象用于构建要发送给客户端的 HTTP 响应,支持设置状态码、头、正文等内容。
常用功能块
-
获取请求信息:通过 Request 对象获取客户端的 IP 地址、用户代理、请求方法等信息。
- 示例:
from fastapi import Request, FastAPI app = FastAPI() @app.get("/info/") async def get_request_info(request: Request): client_host = request.client.host user_agent = request.headers.get("User-Agent") method = request.method return {"client_host": client_host, "user_agent": user_agent, "method": method}
-
自定义响应内容:使用 Response 对象构建自定义的响应,包括设置状态码、头和正文。
- 示例:
from fastapi import Response, FastAPI app = FastAPI() @app.get("/custom-response/") async def custom_response(): content = "Custom response content" headers = {"X-Custom-Header": "value"} return Response(content=content, status_code=200, headers=headers)
-
处理请求正文:获取和解析请求的正文内容,支持不同的媒体类型。
- 示例:
@app.post("/process-body/") async def process_body(request: Request): body = await request.body() # 处理请求正文 return {"body_length": len(body)}
-
重定向响应:发送重定向响应,将客户端引导到另一个 URL。
- 示例:
from fastapi import status @app.get("/redirect/") async def redirect(): return Response(status_code=status.HTTP_302_FOUND, headers={"Location": "/new-url/"})
-
流式响应:对于大文件下载或实时数据推送,使用流式响应逐步发送数据。
- 示例:
from fastapi import FastAPI from fastapi.responses import StreamingResponse app = FastAPI() async def fake_video_streamer(): for i in range(10): yield b"some fake video bytes" await asyncio.sleep(0.1) @app.get("/streaming-video/") async def streaming_video(): return StreamingResponse(fake_video_streamer(), media_type="video/mp4")
高阶使用功能块
-
中间件中处理请求与响应:在中间件中对请求和响应进行全局处理,如日志记录、认证授权等。
- 示例:记录请求和响应的日志
from fastapi import Request, Response from fastapi.middleware import Middleware class LoggingMiddleware: async def __call__(self, request: Request, call_next): start_time = time.time() response = await call_next(request) process_time = time.time() - start_time logger.info( f"{request.method} {request.url} - {response.status_code} - {process_time:.4f}s" ) return response app = FastAPI() app.add_middleware(LoggingMiddleware)
-
自定义响应类:继承 Response 类创建自定义的响应类型,满足特定的业务需求。
- 示例:创建带有自定义头的响应类
from fastapi.responses import Response class CustomResponse(Response): media_type = "application/json" def __init__(self, content=None, status_code=200, headers=None): super().__init__(content=content, status_code=status_code, headers=headers) self.headers["X-Custom-Header"] = "value" @app.get("/custom-response-class/") async def custom_response_class(): return CustomResponse(content={"message": "Custom response"})
-
处理跨域请求:通过设置响应头支持跨域资源共享(CORS),允许不同域的客户端访问 API。
- 示例:设置 CORS 响应头
from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware app = FastAPI() app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) @app.get("/cors-enabled/") async def cors_enabled(): return {"message": "CORS enabled"}
-
处理文件下载响应:发送文件作为响应,支持断点续传和不同的文件类型。
- 示例:发送文件下载响应
from fastapi.responses import FileResponse @app.get("/download-file/") async def download_file(): file_path = "large-video.mp4" return FileResponse( path=file_path, media_type="video/mp4", filename="downloaded-video.mp4" )
-
响应的缓存控制:通过设置缓存头控制客户端或代理服务器对响应的缓存行为,提高性能和减少带宽消耗。
- 示例:设置缓存控制头
@app.get("/cached-response/") async def cached_response(): headers = {"Cache-Control": "max-age=3600, public"} return Response(content="Cached content", headers=headers)
七、APIRouter 路由管理
功能概述
APIRouter 是 FastAPI 提供的路由管理工具,用于将相关的路由分组到不同的模块或文件中,便于大型应用的组织和维护,同时支持中间件、依赖项等的独立配置。
常用功能块
-
路由分组:将相关的路由函数组织到一个 APIRouter 实例中,便于模块化开发。
- 示例:
from fastapi import APIRouter, FastAPI router = APIRouter() @router.get("/items/") async def read_items(): return [{"item_id": "Foo"}] @router.get("/users/") async def read_users(): return [{"username": "John"}] app = FastAPI() app.include_router(router)
-
路由前缀与标签:为路由组设置统一的前缀和标签,方便 API 文档的组织和阅读。
- 示例:
router = APIRouter(prefix="/api", tags=["items"]) @router.get("/items/") async def read_items(): return [{"item_id": "Foo"}] app = FastAPI() app.include_router(router)
-
依赖项注入:为路由组设置全局的依赖项,所有路由函数都可以继承使用。
- 示例:
from fastapi import Depends, Security def get_api_key(api_key: str = Header(...)): # 验证 API 密钥 return api_key router = APIRouter(dependencies=[Depends(get_api_key)]) @router.get("/items/") async def read_items(): return [{"item_id": "Foo"}] app = FastAPI() app.include_router(router)
-
中间件支持:为路由组添加特定的中间件,处理请求和响应的全局逻辑。
- 示例:
from fastapi import Request, Response class LoggingMiddleware: async def __call__(self, request: Request, call_next): start_time = time.time() response = await call_next(request) process_time = time.time() - start_time print(f"Request: {request.method} {request.url} - {process_time:.4f}s") return response router = APIRouter() router.add_middleware(LoggingMiddleware) @router.get("/items/") async def read_items(): return [{"item_id": "Foo"}] app = FastAPI() app.include_router(router)
-
路由的版本控制:通过路由前缀或参数实现 API 的版本控制,方便不同版本的兼容和维护。
- 示例:使用路由前缀实现版本控制
v1_router = APIRouter(prefix="/v1") v2_router = APIRouter(prefix="/v2") @v1_router.get("/items/") async def read_items_v1(): return [{"item_id": "Foo_v1"}] @v2_router.get("/items/") async def read_items_v2(): return [{"item_id": "Foo_v2"}] app = FastAPI() app.include_router(v1_router) app.include_router(v2_router)
高阶使用功能块
-
动态路由注册:根据配置或数据库动态注册路由,实现灵活的路由管理。
- 示例:从配置文件加载路由
from importlib import import_module def load_routes(config): for route_config in config: module = import_module(route_config["module"]) router = getattr(module, "router") app.include_router(router, **route_config.get("kwargs", {})) app = FastAPI() load_routes(config.ROUTES)
-
路由的条件注册:根据环境、配置或其他条件决定是否注册某些路由。
- 示例:仅在调试模式下注册调试路由
if settings.DEBUG: debug_router = APIRouter() @debug_router.get("/debug-info/") async def debug_info(): return {"debug": True} app.include_router(debug_router)
-
路由的组合与嵌套:将多个 APIRouter 实例组合或嵌套使用,构建复杂的路由结构。
- 示例:嵌套路由
admin_router = APIRouter(prefix="/admin") @admin_router.get("/users/") async def read_admin_users(): return [{"username": "admin"}] app = FastAPI() app.include_router(admin_router)
-
路由的性能监控:为路由组添加性能监控中间件,收集路由的性能数据。
- 示例:使用 Prometheus 监控路由性能
from prometheus_fastapi_instrumentator import Instrumentator router = APIRouter() @router.get("/items/") async def read_items(): return [{"item_id": "Foo"}] app = FastAPI() app.include_router(router) Instrumentator().instrument(app).expose()
-
路由的访问控制:为路由组设置访问控制逻辑,限制只有授权用户或 IP 地址才能访问。
- 示例:基于 IP 的访问控制
from fastapi import Request, HTTPException ALLOWED_IPS = ["127.0.0.1"] @app.middleware("http") async def ip_filter(request: Request, call_next): client_host = request.client.host if client_host not in ALLOWED_IPS: raise HTTPException(status_code=403, detail="Forbidden") response = await call_next(request) return response router = APIRouter() @router.get("/protected-items/") async def read_protected_items(): return [{"item_id": "Protected"}] app = FastAPI() app.include_router(router)
八、WebSocket 实时通信
功能概述
WebSocket 提供了在客户端和服务器之间建立双向通信通道的能力,适用于需要实时交互的应用场景,如聊天应用、在线游戏、实时数据监控等。
常用功能块
-
建立 WebSocket 连接:通过定义 WebSocket 路由处理函数,接受客户端的连接请求。
- 示例:
from fastapi import WebSocket, FastAPI app = FastAPI() @app.websocket("/ws") async def websocket_endpoint(websocket: WebSocket): await websocket.accept() while True: data = await websocket.receive_text() await websocket.send_text(f"Message text was: {data}")
-
发送与接收消息:在 WebSocket 连接建立后,发送和接收文本或二进制消息。
- 示例:
@app.websocket("/ws") async def websocket_endpoint(websocket: WebSocket): await websocket.accept() while True: text_data = await websocket.receive_text() await websocket.send_text(f"Echo: {text_data}") bytes_data = await websocket.receive_bytes() await websocket.send_bytes(bytes_data)
-
连接管理:维护活动的 WebSocket 连接列表,方便广播消息或处理连接状态变化。
- 示例:
active_connections = [] @app.websocket("/ws") async def websocket_endpoint(websocket: WebSocket): await websocket.accept() active_connections.append(websocket) try: while True: data = await websocket.receive_text() for connection in active_connections: await connection.send_text(data) except WebSocketDisconnect: active_connections.remove(websocket)
-
消息格式处理:对 WebSocket 消息进行序列化和反序列化,支持 JSON、XML 等格式。
- 示例:处理 JSON 消息
import json @app.websocket("/ws") async def websocket_endpoint(websocket: WebSocket): await websocket.accept() while True: json_data = await websocket.receive_json() processed_data = process_json(json_data) await websocket.send_json(processed_data)
-
异常处理与连接关闭:捕获 WebSocket 连接过程中的异常,优雅地关闭连接并清理资源。
- 示例:
@app.websocket("/ws") async def websocket_endpoint(websocket: WebSocket): await websocket.accept() try: while True: data = await websocket.receive_text() await websocket.send_text(f"Message: {data}") except WebSocketException as e: print(f"WebSocket error: {e}") finally: await websocket.close()
高阶使用功能块
-
WebSocket 的认证与授权:在 WebSocket 连接建立前或建立后进行认证和授权检查,确保只有合法用户才能访问。
- 示例:基于查询参数的认证
from fastapi import Query @app.websocket("/ws") async def websocket_endpoint( websocket: WebSocket, token: str = Query(...) ): # 验证 token if not validate_token(token): await websocket.close(code=status.WS_1008_POLICY_VIOLATION) return await websocket.accept() # 处理连接
-
WebSocket 的负载均衡与扩展:在高并发场景下,通过负载均衡器将 WebSocket 连接分发到多个服务器实例,提高系统的可扩展性。
- 示例:使用 Redis 发布/订阅模式实现跨服务器广播
import aioredis redis = aioredis.from_url("redis://localhost") @app.websocket("/ws") async def websocket_endpoint(websocket: WebSocket): await websocket.accept() # 订阅 Redis 通道 async def pubsub_listener(channel): async for message in channel.iter(): await websocket.send_text(message.decode()) pubsub = redis.pubsub() await pubsub.subscribe("broadcast") asyncio.create_task(pubsub_listener(pubsub)) try: while True: data = await websocket.receive_text() # 发布消息到 Redis 通道 await redis.publish("broadcast", data) except WebSocketDisconnect: await pubsub.unsubscribe("broadcast")
-
WebSocket 的性能优化:对 WebSocket 连接进行性能优化,如减少消息的序列化开销、使用二进制帧传输等。
- 示例:使用 Protobuf 序列化消息
import protobuf # 假设已定义好 protobuf 消息格式 @app.websocket("/ws") async def websocket_endpoint(websocket: WebSocket): await websocket.accept() while True: bytes_data = await websocket.receive_bytes() message = protobuf.Message() message.ParseFromString(bytes_data) # 处理消息 response = protobuf.Response() response_data = response.SerializeToString() await websocket.send_bytes(response_data)
-
WebSocket 的监控与日志:记录 WebSocket 连接的活动日志,监控连接数、消息吞吐量等指标,便于性能分析和故障排查。
- 示例:使用 Prometheus 监控 WebSocket 指标
from prometheus_client import Counter, Gauge ws_connections = Gauge("websocket_connections", "Number of active WebSocket connections") ws_messages = Counter("websocket_messages", "Total number of WebSocket messages", labelnames=["type"]) @app.websocket("/ws") async def websocket_endpoint(websocket: WebSocket): ws_connections.inc() try: while True: data = await websocket.receive_text() ws_messages.labels("text").inc() await websocket.send_text(data) except WebSocketDisconnect: ws_connections.dec()
-
WebSocket 的安全增强:采取措施防止 WebSocket 连接被恶意利用,如限制消息大小、防止 XSS 攻击等。
- 示例:限制接收消息的最大大小
MAX_MESSAGE_SIZE = 1024 * 1024 # 1MB @app.websocket("/ws") async def websocket_endpoint(websocket: WebSocket): await websocket.accept() while True: data = await websocket.receive_text() if len(data) > MAX_MESSAGE_SIZE: await websocket.close(code=status.WS_1009_MESSAGE_TOO_BIG) break # 处理消息