FastAPI 基础

FastAPI 单元子单元

一、FastAPI 核心类

功能概述

FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,基于标准 Python 类型提示。它允许开发者快速构建、测试和部署 RESTful API 服务,同时提供自动化的交互式 API 文档。

常用功能块

  1. 路由定义:通过装饰器如 @app.get()@app.post() 等定义不同的 HTTP 方法对应的路由处理函数。

    • 示例:
    from fastapi import FastAPI
    
    app = FastAPI()
    
    @app.get("/")
    async def read_root():
        return {"message": "Hello World"}
    
  2. 参数解析:自动解析路径参数、查询参数、请求体等,支持复杂数据类型的验证和转换。

    • 示例:
    @app.get("/items/{item_id}")
    async def read_item(item_id: int, q: str = None):
        return {"item_id": item_id, "q": q}
    
  3. 依赖注入:通过 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}
    
  4. 中间件支持:可以添加中间件来处理跨域请求、请求日志记录等全局功能。

    • 示例:
    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=["*"],
    )
    
  5. 自动文档生成:内置了交互式的 API 文档,如 Swagger UI 和 ReDoc,方便开发者和调用者查看和测试 API。

    • 示例:启动应用后访问 http://localhost:8000/docshttp://localhost:8000/redoc 即可查看自动生成的文档。

高阶使用功能块

  1. 自定义异常处理:可以定义自定义的异常处理器来处理特定的异常情况,返回统一的错误响应格式。

    • 示例:
    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"},
        )
    
  2. 异步支持:充分利用 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
    
  3. 数据校验与转换:结合 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()
    
  4. 支持 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}")
    
  5. 插件生态系统:丰富的第三方插件支持,如数据库集成、认证授权、缓存等,可以快速扩展应用的功能。

    • 示例:使用 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 连接时,执行一些耗时的后台任务,而不需要让客户端等待这些任务完成。这在发送邮件、处理日志、清理数据等场景中非常有用。

常用功能块

  1. 添加后台任务:通过将函数作为参数传递给 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"}
    
  2. 传递参数给后台任务:可以向后台任务函数传递多个参数,包括从请求中获取的数据。

    • 示例:
    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"}
    
  3. 后台任务的依赖注入:后台任务也可以使用依赖注入来获取所需的数据或服务。

    • 示例:
    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"}
    
  4. 后台任务的异常处理:可以为后台任务定义异常处理逻辑,捕获任务执行过程中可能出现的错误。

    • 示例:
    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"}
    
  5. 后台任务的状态监控:通过一些机制(如数据库记录、消息队列等)监控后台任务的执行状态,以便后续查询或处理。

    • 示例:
    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"}
    

高阶使用功能块

  1. 后台任务的优先级控制:根据任务的重要性和紧急程度,设置不同的优先级,确保高优先级任务优先执行。

    • 示例:
    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"}
    
  2. 后台任务的分布式执行:在多服务器或容器环境下,将后台任务分布到不同的工作进程或机器上执行,提高任务处理的并发能力和可靠性。

    • 示例:使用 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"}
    
  3. 后台任务的进度跟踪与反馈:对于长时间运行的任务,向客户端提供任务进度的实时反馈,增强用户体验。

    • 示例:通过 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"}
    
  4. 后台任务的资源限制与隔离:对后台任务的资源使用(如内存、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"}
    
  5. 后台任务的调度与计划:根据业务需求,定期或按照特定的时间计划执行后台任务,如定时备份数据、定时发送报告等。

    • 示例:使用 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 提供了对文件上传的处理能力,支持单文件和多文件上传,能够获取文件的内容、文件名、内容类型等信息,并方便地将文件保存到服务器或进行进一步的处理。

常用功能块

  1. 单文件上传:通过 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}
    
  2. 多文件上传:允许用户同时上传多个文件,并对每个文件进行处理。

    • 示例:
    @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]}
    
  3. 文件保存到服务器:将上传的文件保存到服务器的指定目录。

    • 示例:
    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)}
    
  4. 文件类型验证:根据文件的扩展名或 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}
    
  5. 大文件上传处理:对于大文件上传,可以设置文件大小限制,并采用分块读取的方式处理文件内容,避免内存溢出。

    • 示例:
    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}
    

高阶使用功能块

  1. 文件内容流式处理:对于需要实时处理的文件,如视频流、日志流等,采用流式读取和处理的方式,提高效率和响应速度。

    • 示例:
    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")
    
  2. 文件上传的并发控制:限制同时上传的文件数量,防止服务器资源被过多占用。

    • 示例:
    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
    
  3. 文件上传的断点续传:支持大文件上传的断点续传功能,提高上传的可靠性和用户体验。

    • 示例:使用范围请求头实现断点续传
    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}
    
  4. 文件上传的安全增强:对上传的文件进行病毒扫描、内容过滤等安全检查,防止恶意文件上传。

    • 示例:集成第三方病毒扫描工具
    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")
    
  5. 文件上传的元数据处理:提取文件的元数据(如 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 连接过程中处理异常情况,如关闭连接、发送错误消息等。

常用功能块

  1. 自定义 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}
    
  2. 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)
    
  3. 全局异常处理器:定义全局的异常处理器,捕获所有未处理的异常并返回统一的错误响应格式。

    • 示例:
    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"},
        )
    
  4. 异常处理的依赖注入:在异常处理过程中使用依赖注入获取所需的服务或数据。

    • 示例:
    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},
        )
    
  5. 异常处理的扩展功能:根据不同的异常类型返回不同的响应格式,如 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
            )
    

高阶使用功能块

  1. 异常处理的中间件集成:将异常处理逻辑集成到中间件中,实现更灵活的错误处理和日志记录。

    • 示例:
    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)
    
  2. 分布式追踪与异常监控:结合分布式追踪系统和异常监控工具,记录异常发生的上下文信息,便于排查和分析问题。

    • 示例:使用 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},
        )
    
  3. 异常处理的自动化测试:编写自动化测试用例,验证异常处理逻辑的正确性和一致性。

    • 示例:使用 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"
    
  4. 异常处理的性能优化:对异常处理逻辑进行性能优化,减少不必要的计算和 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
    
  5. 多语言异常处理支持:根据客户端的语言偏好返回不同语言的错误信息,提升国际化应用的用户体验。

    • 示例:根据 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、查询参数、路径参数等)获取数据,并支持数据验证、依赖注入、安全认证等功能,使参数处理更加灵活和可靠。

常用功能块

  1. 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()
    
  2. 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}
    
  3. 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"}]}
    
  4. 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}
    
  5. Form:处理表单数据:从表单提交的数据中获取字段值,支持多值和文件上传。

    • 示例:
    from fastapi import Form
    
    @app.post("/login/")
    async def login(username: str = Form(...), password: str = Form(...)):
        return {"username": username}
    
  6. Header:获取请求头:从请求头中获取特定的值,支持自定义头和数据验证。

    • 示例:
    from fastapi import Header
    
    @app.get("/items/")
    async def read_items(user_agent: str = Header(None)):
        return {"User-Agent": user_agent}
    
  7. 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}
    
  8. Query:查询参数:从 URL 查询字符串中获取参数值,支持默认值、别名和数据验证。

    • 示例:
    from fastapi import Query
    
    @app.get("/items/")
    async def read_items(q: str = Query(None, min_length=3)):
        return {"q": q}
    
  9. 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
    

高阶使用功能块

  1. 组合参数处理:将多个参数处理函数组合使用,处理复杂的请求数据结构。

    • 示例:同时处理 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}
    
  2. 自定义参数验证逻辑:通过定义 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()
    
  3. 参数处理的性能优化:对参数处理逻辑进行性能优化,如缓存验证结果、减少不必要的计算等。

    • 示例:缓存路径参数的验证结果
    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}
    
  4. 参数处理的国际化支持:根据客户端的语言偏好,对参数的错误信息进行多语言转换。

    • 示例:使用 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()
    
  5. 参数处理的扩展功能:通过继承和扩展参数处理函数,实现特定的业务逻辑和功能。

    • 示例:扩展 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 响应,支持设置状态码、头、正文等内容。

常用功能块

  1. 获取请求信息:通过 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}
    
  2. 自定义响应内容:使用 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)
    
  3. 处理请求正文:获取和解析请求的正文内容,支持不同的媒体类型。

    • 示例:
    @app.post("/process-body/")
    async def process_body(request: Request):
        body = await request.body()
        # 处理请求正文
        return {"body_length": len(body)}
    
  4. 重定向响应:发送重定向响应,将客户端引导到另一个 URL。

    • 示例:
    from fastapi import status
    
    @app.get("/redirect/")
    async def redirect():
        return Response(status_code=status.HTTP_302_FOUND, headers={"Location": "/new-url/"})
    
  5. 流式响应:对于大文件下载或实时数据推送,使用流式响应逐步发送数据。

    • 示例:
    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")
    

高阶使用功能块

  1. 中间件中处理请求与响应:在中间件中对请求和响应进行全局处理,如日志记录、认证授权等。

    • 示例:记录请求和响应的日志
    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)
    
  2. 自定义响应类:继承 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"})
    
  3. 处理跨域请求:通过设置响应头支持跨域资源共享(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"}
    
  4. 处理文件下载响应:发送文件作为响应,支持断点续传和不同的文件类型。

    • 示例:发送文件下载响应
    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"
        )
    
  5. 响应的缓存控制:通过设置缓存头控制客户端或代理服务器对响应的缓存行为,提高性能和减少带宽消耗。

    • 示例:设置缓存控制头
    @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 提供的路由管理工具,用于将相关的路由分组到不同的模块或文件中,便于大型应用的组织和维护,同时支持中间件、依赖项等的独立配置。

常用功能块

  1. 路由分组:将相关的路由函数组织到一个 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)
    
  2. 路由前缀与标签:为路由组设置统一的前缀和标签,方便 API 文档的组织和阅读。

    • 示例:
    router = APIRouter(prefix="/api", tags=["items"])
    
    @router.get("/items/")
    async def read_items():
        return [{"item_id": "Foo"}]
    
    app = FastAPI()
    app.include_router(router)
    
  3. 依赖项注入:为路由组设置全局的依赖项,所有路由函数都可以继承使用。

    • 示例:
    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)
    
  4. 中间件支持:为路由组添加特定的中间件,处理请求和响应的全局逻辑。

    • 示例:
    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)
    
  5. 路由的版本控制:通过路由前缀或参数实现 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)
    

高阶使用功能块

  1. 动态路由注册:根据配置或数据库动态注册路由,实现灵活的路由管理。

    • 示例:从配置文件加载路由
    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)
    
  2. 路由的条件注册:根据环境、配置或其他条件决定是否注册某些路由。

    • 示例:仅在调试模式下注册调试路由
    if settings.DEBUG:
        debug_router = APIRouter()
    
        @debug_router.get("/debug-info/")
        async def debug_info():
            return {"debug": True}
    
        app.include_router(debug_router)
    
  3. 路由的组合与嵌套:将多个 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)
    
  4. 路由的性能监控:为路由组添加性能监控中间件,收集路由的性能数据。

    • 示例:使用 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()
    
  5. 路由的访问控制:为路由组设置访问控制逻辑,限制只有授权用户或 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 提供了在客户端和服务器之间建立双向通信通道的能力,适用于需要实时交互的应用场景,如聊天应用、在线游戏、实时数据监控等。

常用功能块

  1. 建立 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}")
    
  2. 发送与接收消息:在 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)
    
  3. 连接管理:维护活动的 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)
    
  4. 消息格式处理:对 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)
    
  5. 异常处理与连接关闭:捕获 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()
    

高阶使用功能块

  1. 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()
        # 处理连接
    
  2. 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")
    
  3. 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)
    
  4. 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()
    
  5. 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
            # 处理消息
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值