likes
comments
collection
share

(四)深入理解 ASGI 和 Uvicorn:FastAPI 的基础概念

作者站长头像
站长
· 阅读数 28

在现代 Web 开发中,ASGIUvicorn是理解和使用 FastAPI 的关键组件。本文将深入解析 ASGI 和 Uvicorn,并简要介绍 FastAPI 的路由和请求参数处理,同时深入探讨中间件与依赖注入。

1. 什么是 ASGI?

ASGI(Asynchronous Server Gateway Interface)是一个为 Python 网络服务器和应用程序设计的异步标准接口。它是 WSGI(Web Server Gateway Interface)的异步版本,旨在支持 WebSockets、HTTP/2 以及其他需要异步通信的现代协议。

ASGI 的特点:

  • 异步支持:允许处理异步请求,提高并发性能。
  • 灵活性:支持 HTTP、WebSockets 等多种协议。
  • 标准化:提供统一接口,方便不同框架和服务器之间的互操作性。

2. 什么是 Uvicorn?

Uvicorn 是一个基于 ASGI 的高性能 Web 服务器,用于运行 ASGI 应用(例如 FastAPI)。Uvicorn 使用 uvloop 和 httptools,以提供卓越的性能和快速的响应时间。

Uvicorn 的优势:

  • 高性能:基于 uvloop 和 httptools,极大提升了处理速度。
  • 轻量级:设计简洁,启动速度快,占用资源少。
  • 易于使用:简单的命令行界面,方便开发和部署。

安装 Uvicorn

pip install "uvicorn[standard]"

运行 FastAPI 应用

uvicorn main:app --reload

在命令中,main是你的 Python 文件名(不带.py后缀),app是 FastAPI 实例。--reload标志用于在代码修改时自动重启服务器,非常适合开发环境。

3. FastAPI 的路由

FastAPI 使用装饰器来定义路径操作(Route)。路径操作是指 API 的具体端点,例如 GET、POST 请求。

定义简单的 GET 请求

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def read_root():
    return {"message": "Hello, World!"}

在这个示例中,当访问根路径(/)时,将会返回一个包含 message 键的 JSON 响应。

定义带有路径参数的请求

@app.get("/items/{item_id}")
async def read_item(item_id: int):
    return {"item_id": item_id}

在这个示例中,item_id是一个路径参数,FastAPI 会自动将其转换为指定的类型(如 int),并传递给视图函数。

4. 请求参数和验证

FastAPI 支持多种类型的请求参数,包括路径参数、查询参数、请求体参数等,并通过 Pydantic 进行验证。

查询参数

@app.get("/items/")
async def read_item(name: str, age: int):
    return {"name": name, "age": age}

在这个示例中,nameage是查询参数,访问 http://127.0.0.1:8000/items/?name=John&age=30 会返回{"name": "John", "age": 30}

请求体参数

from pydantic import BaseModel

class Item(BaseModel):
    name: str
    price: float
    is_offer: bool = None

@app.post("/items/")
async def create_item(item: Item):
    return item

在这个示例中,Item是一个Pydantic模型,定义了请求体的结构和验证规则。当创建一个新的 Item 时,FastAPI 会自动验证请求体数据,并将其解析为 Item 实例。

5. 中间件

中间件是指在处理请求和响应之间插入的一段处理逻辑,通常用于执行诸如日志记录、认证、修改请求和响应等任务。

使用中间件

from fastapi import FastAPI, Request
import time

app = FastAPI()

@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
    start_time = time.time()
    response = await call_next(request)
    process_time = time.time() - start_time
    response.headers["X-Process-Time"] = str(process_time)
    return response
  • @app.middleware("http")用于注册一个 HTTP 中间件函数,该函数会在每个请求处理之前和之后执行。具体来说,它在请求进入任何路径操作函数之前执行一些预处理逻辑,并且在路径操作函数处理完请求之后执行一些后处理逻辑。如果注册了多个 HTTP 中间件函数,它们的执行顺序是按注册的顺序执行。

在这个示例中,中间件会在每个请求处理前后记录处理时间,并将其添加到响应头中。

6. 依赖注入与 Depends 的使用

依赖注入(Dependency Injection)是一个设计模式,它使得对象之间的依赖关系通过外部注入而不是内部创建,从而提高代码的可维护性和可测试性。FastAPI 提供了强大的依赖注入系统,允许你在路径操作函数中声明依赖项,FastAPI 会自动解决这些依赖关系。

Depends 是实现依赖注入的核心工具。它允许你在路径操作函数中声明依赖项,FastAPI 会自动调用这些依赖项并将返回值传递给路径操作函数。

简单的依赖注入

from fastapi import Depends, FastAPI

app = FastAPI()

def common_parameters(q: str = None, skip: int = 0, limit: int = 10):
    return {"q": q, "skip": skip, "limit": limit}

@app.get("/items/")
async def read_items(commons: dict = Depends(common_parameters)):
    return commons
  • 在这个示例中,common_parameters 是一个依赖项,定义了一组常用参数。read_items 路由通过 Depends 函数引入这些参数,从而实现参数复用。

依赖注入的高级用法

from fastapi import Depends, FastAPI, HTTPException
from fastapi.security import OAuth2PasswordBearer
from typing import Optional

app = FastAPI()

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

async def get_current_user(token: str = Depends(oauth2_scheme)):
    if token != "fake-token":
        raise HTTPException(status_code=401, detail="Invalid token")
    return {"username": "fake-user"}

@app.get("/users/me")
async def read_users_me(current_user: dict = Depends(get_current_user)):
    return current_user
  • 在这个示例中,get_current_user 是一个依赖项,用于从请求中提取和验证OAuth2 token。如果 token 无效,将抛出 HTTPExceptionread_users_me 路由通过 Depends 函数引入 get_current_user 依赖项,从而实现认证逻辑。

(四)深入理解 ASGI 和 Uvicorn:FastAPI 的基础概念

(四)深入理解 ASGI 和 Uvicorn:FastAPI 的基础概念

ASGIUvicorn 是 FastAPI 高性能和异步能力的基础。通过深入理解这两个组件,你可以更好地利用 FastAPI 构建高性能、高并发的 Web 应用。结合 FastAPI 的自动文档生成和数据验证功能,你能够快速开发和维护现代 Web 应用。中间件和依赖注入进一步增强了 FastAPI 的功能和灵活性,使得开发变得更加高效和可维护。

希望这篇文章能帮助你深入理解 ASGI 和 Uvicorn 的基础概念,为你的高级编程实践奠定坚实的基础。如果你有任何问题或需要进一步的帮助,请随时联系我。

转载自:https://juejin.cn/post/7379437165484523557
评论
请登录