fastapi之中间件

中间件

在 FastAPI 中,中间件是一个功能强大的组件,用于处理请求和响应之间的各种横切关注点(cross-cutting concerns)。中间件允许你在请求被处理前后执行代码,这非常适合实现如日志记录、安全控制、数据处理和跨域资源共享(CORS)等功能。

定义

中间件是介于接收请求和发送响应之间的一个软件层。在 FastAPI 应用中,所有的请求首先经过一系列的中间件,然后才到达实际的业务逻辑处理函数;响应也会在返回给客户之前经过这些中间件。因此,中间件是处理全局任务的理想选择。

使用

在 FastAPI 中添加中间件通常涉及几个步骤,其中涉及到选择合适的中间件组件并配置其参数。以下是一个如何设置 CORS 中间件的例子,这个中间件用于允许或限制跨域请求。

示例-配置 CORS 中间件

跨源资源共享(CORS)是一个安全特性,允许或限制网页上的资源可以被另一个域名的网页访问。在 API 开发中配置 CORS 是常见需求,尤其是当你的前端和后端部署在不同的域时。

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
import uvicorn
import os

app = FastAPI()

# 配置 CORS 中间件
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["GET", "POST", "PUT", "DELETE"],
    allow_headers=["X-Custom-Header", "Content-Type"],
)


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


@app.post("/submit")
async def submit_form(data: dict):
    return {"received_data": data}


if __name__ == "__main__":
    uvicorn.run(
        f"{os.path.basename(__file__).split('.')[0]}:app",
        host="127.0.0.1",
        port=8000,
        reload=True,
    )

解释说明

  1. 导入依赖
  • from fastapi import FastAPI: 导入 FastAPI,用于创建 API 应用。
  • from fastapi.middleware.cors import CORSMiddleware: 导入 CORS 中间件,用于配置跨域资源共享。
  1. 应用实例

app = FastAPI(): 创建一个 FastAPI 应用实例。

  1. 添加 CORS 中间件

app.add_middleware(CORSMiddleware, ...): 将 CORS 中间件添加到应用中。这一步是配置 CORS 支持的关键。

  1. CORS 中间件参数

allow_origins: 定义哪些来源域可以访问资源。在此示例中,https://example.comhttps://www.anotherdomain.com 被允许访问。这可以是一个具体的域名列表或 ["*"](允许所有域)。

  • allow_credentials: 允许前端在请求中携带认证信息(如 Cookies)。这是一个布尔值。
  • allow_methods: 指定允许的 HTTP 方法,如["GET", "POST", "PUT", "DELETE"]
    allow_headers: 允许的 HTTP 请求头列表,这里允许 X-Custom-HeaderContent-Type
  1. API 端点

定义了两个端点 main()submit_form() 来演示如何在启用了 CORS 的应用中处理请求。

测试

allow_origins=[] # 不允许任何源

在这里插入图片描述

allow_origins=["*"] # 允许任何源

在这里插入图片描述

其他中间件

自定义日志记录中间件

自定义中间件可以用来实现例如日志记录等功能,这对于调试和监控应用状态非常有用。

from fastapi import FastAPI, Request, HTTPException
from starlette.middleware.base import BaseHTTPMiddleware
from fastapi.responses import JSONResponse, PlainTextResponse
import time
import uvicorn
import os


class LoggingMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next):
        start_time = time.time()
        response = await call_next(request)
        process_time = time.time() - start_time

        # 记录请求和响应的详细信息
        log_message = (
            f"请求方法: {request.method}\n"
            f"请求路径: {request.url.path}\n"
            f"响应状态: {response.status_code}\n"
            f"处理时间: {process_time:.4f} 秒"
        )
        print(log_message)  # 在生产环境中,可以将这些信息写入日志文件

        return response


app = FastAPI()

# 添加中间件到应用中
app.add_middleware(LoggingMiddleware)


# 使用 PlainTextResponse 返回简单文本响应
@app.get("/", response_class=PlainTextResponse)
async def read_root():
    # 可以直接返回字符串,FastAPI 会自动封装为 PlainTextResponse
    return "Hello, World!"


# 使用 JSONResponse 创建一个更复杂的 JSON 响应
@app.post("/items/", response_class=JSONResponse)
async def create_item(item: dict):
    # 检查输入是否包含必要的字段
    if "name" not in item:
        raise HTTPException(status_code=400, detail="Missing 'name' field in the item")

    # 模拟创建项目并返回包含项目信息的响应
    response_data = {"item_name": item.get("name"), "item_id": 123}
    return JSONResponse(content=response_data, status_code=201)


if __name__ == "__main__":
    uvicorn.run(
        f"{os.path.basename(__file__).split('.')[0]}:app",
        host="127.0.0.1",
        port=8000,
        reload=True,
    )

解释说明

  1. 中间件类 LoggingMiddleware:
  • 继承自 BaseHTTPMiddleware,重写 dispatch 方法来拦截请求和发送的响应。
  • 使用 call_next(request) 异步调用接下来的请求处理,这将返回一个响应对象。
  • 计算处理请求所需的时间,并构建一个包含请求方法、路径、响应状态和处理时间的日志消息。
  • 使用 print 函数打印日志信息。在实际应用中,选择使用logging 模块或外部日志服务。
  1. 添加中间件:
  • 使用 app.add_middleware(LoggingMiddleware) 将自定义中间件添加到 FastAPI 应用中。
  1. 示例端点:
  • 定义两个简单的 API 端点,read_rootcreate_item,用于演示日志中间件的效果。

测试

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

SessionMiddleware

使用 SessionMiddleware 来管理用户会话,这对于需要追踪用户状态或者保持登录状态的应用尤为重要。

from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from starlette.middleware.sessions import SessionMiddleware
import uvicorn
import os

app = FastAPI()

# 设置 SessionMiddleware,secret_key 应该是一个长随机字符串
app.add_middleware(
    SessionMiddleware, secret_key="!se1cret2-ke3y-sh4ould-b5e-ve8ry-se8cure!"
)


@app.get("/", response_class=HTMLResponse)
async def read_root(request: Request):
    # 访问会话中的数据
    count = request.session.get("count", 0)
    count += 1
    request.session["count"] = count  # 更新会话数据
    return f"<html><body><h1>Visit Count: {count}</h1></body></html>"


@app.get("/reset")
async def reset_count(request: Request):
    request.session.pop("count", None)  # 重置会话数据
    return {"status": "session reset"}


@app.get("/logout")
async def logout(request: Request):
    request.session.clear()  # 清空所有会话数据
    return {"status": "logged out"}


if __name__ == "__main__":
    uvicorn.run(
        f"{os.path.basename(__file__).split('.')[0]}:app",
        host="127.0.0.1",
        port=8000,
        reload=True,
    )

功能说明

  1. 设置会话中间件:
  • 使用 SessionMiddleware 来管理会话。secret_key 用于签名和/或加密会话 cookie,确保它的安全性。
  1. 首页 (/):
  • 显示页面访问次数。每次访问都会增加计数,这个计数保存在会话中。
  • 使用 HTMLResponse 直接返回 HTML 格式的响应。
  1. 重置计数 (/reset):
  • 提供一个端点来重置会话中的 count 数据。这可以用于演示会话数据的修改。
  1. 注销 (/logout):
  • 清空会话中的所有数据,模拟用户注销功能。

测试

访问次数

在这里插入图片描述

重置次数

在这里插入图片描述
在这里插入图片描述

清空会话并注销

在这里插入图片描述

TrustedHostMiddleware

使用 TrustedHostMiddleware 可以提高应用的安全性,限制哪些主机名可以访问应用。

from fastapi import FastAPI
from starlette.middleware.trustedhost import TrustedHostMiddleware

app = FastAPI()

# 添加 TrustedHostMiddleware
app.add_middleware(
    TrustedHostMiddleware,
    allowed_hosts=["example.com", "www.example.com", "*.example.com"]
)

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

功能说明

  1. 添加 TrustedHostMiddleware 中间件:
  • allowed_hosts 参数定义了可以接受请求的主机名列表。在这个例子中,允许从 example.comwww.example.com,以及任何以 example.com 结尾的子域名接受请求。
  • 可以根据需要调整这个列表来包括你的部署环境中的实际主机名。
  1. API 端点:
  • 定义了一个简单的 GET 请求处理函数 read_root,它返回一个简单的欢迎消息。

测试

在这里插入图片描述
在这里插入图片描述

与CORSMiddleware的区别

TrustedHostMiddleware
  1. 目的:
  • TrustedHostMiddleware 用于确保接收到的请求来自预定义的一组受信任的主机名。它的主要作用是防止 HTTP Host 头攻击,这种攻击可能会误导应用生成错误的链接、重定向、或被认为是不安全的请求来源。
  1. 工作原理:
  • 当一个请求被接收时,TrustedHostMiddleware 检查 HTTP 请求的 Host 头部是否在允许的主机名列表中。如果不在这个列表中,请求将被拒绝,并返回一个错误响应(通常是 400 Bad Request)。
  1. 使用场景:

适用于所有服务器端应用,特别是在面对公共互联网时,这有助于确保请求确实来自你预期的域。

CORSMiddleware
  1. 目的:
  • CORSMiddleware 旨在支持跨源资源共享 (CORS),允许或限制网页上的资源可以被不同源(域、协议或端口)的网页访问。CORS 主要用于前端 JavaScript 代码,使其能够请求并从不同源加载资源。
  1. 工作原理:
  • CORS 策略要求在发送实际请求前,浏览器首先发送一个预检请求(使用 OPTIONS 方法),从服务器查询哪些源、哪些 HTTP 方法和头部是被允许的。如果服务器的响应表明这个跨源请求是被允许的,浏览器才会发送实际的请求。
  1. 使用场景:
  • 主要用于控制哪些外部源可以访问你的资源,通常用于 API 服务,尤其是当 API 被不同的前端应用调用时。这有助于增加资源访问的灵活性,同时确保安全控制。
对比总结
  • 安全目标不同
    • TrustedHostMiddleware 防止服务器被伪造的或不安全的 Host 头欺骗。
    • CORSMiddleware 允许服务器明确声明哪些跨域请求是合法的,主要防止未授权的跨站读取和互动。
  • 适用环境不同
    • TrustedHostMiddleware 主要用于服务器端安全防护,保护应用不受恶意请求影响。
    • CORSMiddleware 主要解决浏览器同源策略的限制,允许合法的跨源访问。
好的,FastAPI是一款基于Python的现代Web框架,它提供了一些中间件来增强它的功能。中间件可以在请求处理前或处理后执行一些操作,例如记录日志、添加请求头、鉴权等。下面我来介绍一下FastAPI中间件。 1. CORSMiddleware 这个中间件是用来处理跨域请求的。FastAPI自带了这个中间件,可以用来设置允许的跨域请求。使用方法如下: ```python from fastapi.middleware.cors import CORSMiddleware app = FastAPI() origins = [ "http://localhost", "http://localhost:8080", ] app.add_middleware( CORSMiddleware, allow_origins=origins, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) ``` 2. HTTPSRedirectMiddleware 这个中间件是用来将HTTP请求重定向到HTTPS请求的。它可以强制所有HTTP请求都使用HTTPS。使用方法如下: ```python from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware app = FastAPI() app.add_middleware(HTTPSRedirectMiddleware) ``` 3. RequestIDMiddleware 这个中间件为每个请求添加一个唯一的ID,方便跟踪和调试。使用方法如下: ```python from fastapi.middleware.request_id import RequestIDMiddleware app = FastAPI() app.add_middleware(RequestIDMiddleware) ``` 4. AuthenticationMiddleware 这个中间件是用来进行用户认证的。它可以在每个请求处理前,对请求进行鉴权,确保用户有访问权限。使用方法如下: ```python from fastapi.middleware.authentication import AuthenticationMiddleware from myapp.auth import get_current_user app = FastAPI() app.add_middleware(AuthenticationMiddleware, backend=get_current_user) ``` 5. GZipMiddleware 这个中间件是用来启用Gzip压缩的。它可以将响应体进行压缩,减少数据传输量。使用方法如下: ```python from fastapi.middleware.gzip import GZipMiddleware app = FastAPI() app.add_middleware(GZipMiddleware, minimum_size=1000) ``` 以上是FastAPI中常用的一些中间件,它们可以让开发者更方便地实现一些常用的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

trust Tomorrow

感谢支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值