Stories

Detail Return Return

如何在 FastAPI 中巧妙覆蓋依賴注入並攔截第三方服務調用? - Stories Detail


url: /posts/2d992ef9e8962dc0a4a0b5348d486114/
title: 如何在 FastAPI 中巧妙覆蓋依賴注入並攔截第三方服務調用?
date: 2025-09-06T03:34:14+08:00
lastmod: 2025-09-06T03:34:14+08:00
author: cmdragon

summary:
FastAPI 的依賴注入系統允許解耦複雜依賴關係,便於代碼重用。在測試中,可通過 dependencies_overrides 覆蓋真實依賴,避免影響實際服務。多層依賴覆蓋時,需特別注意共享資源(如數據庫連接)的處理。對於第三方服務調用,可使用自定義 HTTP 客户端攔截器實現請求攔截、模擬和降級處理,確保在服務異常時返回降級數據。常見報錯如 422 Unprocessable Entity500 Internal Server Error 可通過模型驗證和異常處理解決,而 TimeoutError 則可通過設置超時和重試機制預防。

categories:

  • fastapi

tags:

  • FastAPI
  • 依賴注入
  • 單元測試
  • 請求攔截
  • 第三方服務調用
  • 錯誤處理
  • 模擬與覆蓋

<img src="" title="cmdragon_cn.png" alt="cmdragon_cn.png"/>

<img src="https://api2.cmdragon.cn/upload/cmder/20250304_012821924.jpg" title="cmdragon_cn.png" alt="cmdragon_cn.png"/>

掃描二維碼關注或者微信搜一搜:編程智域 前端至全棧交流與成長

發現1000+提升效率與開發的AI工具和實用程序:https://tools.cmdragon.cn/

1. 依賴注入系統模擬與覆蓋

1.1 依賴注入的核心概念

FastAPI 的依賴注入系統是其核心特性之一,它允許你將複雜依賴關係解耦並重用代碼。例如數據庫連接、授權驗證等場景:

# 示例:基本依賴注入
from fastapi import Depends, FastAPI

app = FastAPI()

async def common_params(limit: int = 100, offset: int = 0):
    return {"limit": limit, "offset": offset}

@app.get("/items/")
async def read_items(params: dict = Depends(common_params)):
    return {"params": params}

1.2 測試場景中的覆蓋技術

在單元測試中,需要覆蓋真實依賴(如數據庫連接),避免對實際服務產生影響。使用 FastAPI 的 dependencies_overrides

# 測試覆蓋真實數據庫的示例
from fastapi.testclient import TestClient
from .main import app, get_db  # 原始依賴

client = TestClient(app)

# 創建虛假的數據庫依賴
async def fake_db():
    return MockDatabase()

# 覆蓋原始依賴
app.dependency_overrides[get_db] = fake_db

def test_read_items():
    response = client.get("/items")
    assert response.status_code == 200

1.3 多層依賴覆蓋

graph TD
    A[路由處理函數] --> B[依賴A]
    A --> C[依賴B]
    B --> D[子依賴A1]
    C --> E[子依賴B1]
    D --> F[數據庫連接]
    E --> F[數據庫連接]
    
    style F fill:#f9f,stroke:#333

要特別注意底層依賴的覆蓋,比如共享的數據庫連接對象:

# 覆蓋共享資源
class MockDBConnection:
    async def execute(self, query):
        return ["mock_data"]

def override_db():
    return MockDBConnection()

app.dependency_overrides[get_db_connection] = override_db

2. 第三方服務調用的請求攔截

2.1 攔截模式與應用場景

當需要調用外部 API 時,可能遇到:

  • 測試時避免實際 API 調用
  • 實現請求降級(如外部服務宕機)
  • 調試時記錄請求內容
    FastAPI 推薦使用自定義 HTTP 客户端攔截器。

2.2 請求攔截實現

from httpx import AsyncClient, Request, Response

class LoggingClient(AsyncClient):
    async def send(self, request: Request, **kwargs) -> Response:
        print(f"Sending: {request.method} {request.url}")
        return await super().send(request, **kwargs)

# 在路由中使用
@app.get("/external")
async def external_data(
    client: LoggingClient = Depends(lambda: LoggingClient())
):
    response = await client.get("https://api.example.com/data")
    return response.json()

2.3 請求模擬與降級處理

flowchart LR
    A[業務代碼] --> B{攔截器檢查}
    B -->|服務正常| C[調用真實API]
    B -->|服務異常| D[返回緩存數據]
    B -->|測試模式| E[返回模擬數據]
# 完整的攔截器實現
import httpx
from fastapi import Depends

class ResilientClient(AsyncClient):
    def __init__(self, mock_mode=False):
        self.mock_mode = mock_mode
    
    async def send(self, request: Request, **kwargs) -> Response:
        if self.mock_mode:
            return self.create_mock_response(request)
        
        try:
            return await super().send(request, timeout=10, **kwargs)
        except httpx.ConnectError:
            return self.return_fallback_data(request)
    
    def create_mock_response(self, request):
        return Response(200, json={"mock": "data"})
    
    def return_fallback_data(self, request):
        return Response(503, json={"error": "Service unavailable"})

3. 課後 Quiz

  1. 問題: 當覆蓋多層依賴時,需要特別注意哪種共享資源的處理?
    答案: 共享的數據庫連接對象。如果上層依賴和下層依賴使用了相同的數據庫連接,需要確保整個鏈路上的依賴都被正確覆蓋,否則可能造成依賴泄漏。
  2. 問題: 當第三方服務返回 503 錯誤時,我們的攔截器會如何響應?
    答案: 通過 return_fallback_data 方法返回 503 響應和降級數據。這實現了請求降級,避免因外部服務問題導致整個應用不可用。

4. 常見報錯解決方案

4.1 422 Unprocessable Entity

產生原因:

  • Pydantic 模型驗證失敗
  • 依賴項類型不匹配
    解決方案:

    # 檢查模型定義
    class Item(BaseModel):
      name: str  # 確保沒有類型錯誤
      price: float
    
    # 添加驗證提示
    @app.exception_handler(RequestValidationError)
    async def validation_handler(request, exc):
      return JSONResponse(
          status_code=400,
          content=jsonable_encoder({"detail": exc.errors()})
      )

4.2 500 Internal Server Error in Dependency

產生原因:

  • 依賴項函數中出現未處理異常
  • 依賴覆蓋未生效
    解決方案:

    # 增加依賴項的異常處理
    async def secure_dependency():
      try:
          yield connection
      except Exception:
          raise HTTPException(500, "Dependency error")
      finally:
          clean_up_resources()
    
    # 確認測試中執行了覆蓋
    app.dependency_overrides[real_dependency] = mock_dependency

4.3 TimeoutError in HTTP Client

產生原因:

  • 外部API響應超時
  • 網絡波動
    預防建議:

    # 設置合理超時時間
    client = ResilientClient(timeout=5.0)
    
    # 添加重試機制
    import backoff
    @backoff.on_exception(backoff.expo, httpx.RequestError)
    async def safe_request(url):
      return await client.get(url)

餘下文章內容請點擊跳轉至 個人博客頁面 或者 掃碼關注或者微信搜一搜:編程智域 前端至全棧交流與成長,閲讀完整的文章:如何在 FastAPI 中巧妙覆蓋依賴注入並攔截第三方服務調用?

<details>
<summary>往期文章歸檔</summary>

  • 為什麼你的單元測試需要Mock數據庫才能飛起來? - cmdragon's Blog
  • 如何在FastAPI中巧妙隔離依賴項,讓單元測試不再頭疼? - cmdragon's Blog
  • 如何在FastAPI中巧妙隔離依賴項,讓單元測試不再頭疼? - cmdragon's Blog
  • 測試覆蓋率不夠高?這些技巧讓你的FastAPI測試無懈可擊! - cmdragon's Blog
  • 為什麼你的FastAPI測試覆蓋率總是低得讓人想哭? - cmdragon's Blog
  • 如何讓FastAPI測試不再成為你的噩夢? - cmdragon's Blog
  • FastAPI測試環境配置的秘訣,你真的掌握了嗎? - cmdragon's Blog
  • 全鏈路追蹤如何讓FastAPI微服務架構的每個請求都無所遁形? - cmdragon's Blog
  • 如何在API高併發中玩轉資源隔離與限流策略? - cmdragon's Blog
  • 任務分片執行模式如何讓你的FastAPI性能飆升? - cmdragon's Blog
  • 冷熱任務分離:是提升Web性能的終極秘籍還是技術噱頭? - cmdragon's Blog
  • 如何讓FastAPI在百萬級任務處理中依然遊刃有餘? - cmdragon's Blog
  • 如何讓FastAPI與消息隊列的聯姻既甜蜜又可靠? - cmdragon's Blog
  • 如何在FastAPI中巧妙實現延遲隊列,讓任務乖乖等待? - cmdragon's Blog
  • FastAPI的死信隊列處理機制:為何你的消息系統需要它? - cmdragon's Blog
  • 如何讓FastAPI任務系統在失敗時自動告警並自我修復? - cmdragon's Blog
  • 如何用Prometheus和FastAPI打造任務監控的“火眼金睛”? - cmdragon's Blog
  • 如何用APScheduler和FastAPI打造永不宕機的分佈式定時任務系統? - cmdragon's Blog
  • 如何在 FastAPI 中玩轉 APScheduler,讓任務定時自動執行? - cmdragon's Blog
  • 定時任務系統如何讓你的Web應用自動完成那些煩人的重複工作? - cmdragon's Blog
  • Celery任務監控的魔法背後藏着什麼秘密? - cmdragon's Blog
  • 如何讓Celery任務像VIP客户一樣享受優先待遇? - cmdragon's Blog
  • 如何讓你的FastAPI Celery Worker在壓力下優雅起舞? - cmdragon's Blog
  • FastAPI與Celery的完美邂逅,如何讓異步任務飛起來? - cmdragon's Blog
  • FastAPI消息持久化與ACK機制:如何確保你的任務永不迷路? - cmdragon's Blog
  • FastAPI的BackgroundTasks如何玩轉生產者-消費者模式? - cmdragon's Blog
  • BackgroundTasks 還是 RabbitMQ?你的異步任務到底該選誰? - cmdragon's Blog
  • BackgroundTasks與Celery:誰才是異步任務的終極贏家? - cmdragon's Blog
  • 如何在 FastAPI 中優雅處理後台任務異常並實現智能重試? - cmdragon's Blog
  • BackgroundTasks 如何巧妙駕馭多任務併發? - cmdragon's Blog
  • 如何讓FastAPI後台任務像多米諾骨牌一樣井然有序地執行? - cmdragon's Blog
  • FastAPI後台任務:是時候讓你的代碼飛起來了嗎? - cmdragon's Blog
  • FastAPI後台任務為何能讓郵件發送如此絲滑? - cmdragon's Blog
  • FastAPI的請求-響應週期為何需要後台任務分離? - cmdragon's Blog
  • 如何在FastAPI中讓後台任務既高效又不會讓你的應用崩潰? - cmdragon's Blog
  • FastAPI後台任務:異步魔法還是同步噩夢? - cmdragon's Blog
  • 如何在FastAPI中玩轉Schema版本管理和灰度發佈? - cmdragon's Blog
    </details>

<details>
<summary>免費好用的熱門在線工具</summary>

  • ASCII字符畫生成器 - 應用商店 | By cmdragon
  • JSON Web Tokens 工具 - 應用商店 | By cmdragon
  • Bcrypt 密碼工具 - 應用商店 | By cmdragon
  • GIF 合成器 - 應用商店 | By cmdragon
  • GIF 分解器 - 應用商店 | By cmdragon
  • 文本隱寫術 - 應用商店 | By cmdragon
  • CMDragon 在線工具 - 高級AI工具箱與開發者套件 | 免費好用的在線工具
  • 應用商店 - 發現1000+提升效率與開發的AI工具和實用程序 | 免費好用的在線工具
  • CMDragon 更新日誌 - 最新更新、功能與改進 | 免費好用的在線工具
  • 支持我們 - 成為贊助者 | 免費好用的在線工具
  • AI文本生成圖像 - 應用商店 | 免費好用的在線工具
  • 臨時郵箱 - 應用商店 | 免費好用的在線工具
  • 二維碼解析器 - 應用商店 | 免費好用的在線工具
  • 文本轉思維導圖 - 應用商店 | 免費好用的在線工具
  • 正則表達式可視化工具 - 應用商店 | 免費好用的在線工具
  • 文件隱寫工具 - 應用商店 | 免費好用的在線工具
  • IPTV 頻道探索器 - 應用商店 | 免費好用的在線工具
  • 快傳 - 應用商店 | 免費好用的在線工具
  • 隨機抽獎工具 - 應用商店 | 免費好用的在線工具
  • 動漫場景查找器 - 應用商店 | 免費好用的在線工具
  • 時間工具箱 - 應用商店 | 免費好用的在線工具
  • 網速測試 - 應用商店 | 免費好用的在線工具
  • AI 智能摳圖工具 - 應用商店 | 免費好用的在線工具
  • 背景替換工具 - 應用商店 | 免費好用的在線工具
  • 藝術二維碼生成器 - 應用商店 | 免費好用的在線工具
  • Open Graph 元標籤生成器 - 應用商店 | 免費好用的在線工具
  • 圖像對比工具 - 應用商店 | 免費好用的在線工具
  • 圖片壓縮專業版 - 應用商店 | 免費好用的在線工具
  • 密碼生成器 - 應用商店 | 免費好用的在線工具
  • SVG優化器 - 應用商店 | 免費好用的在線工具
  • 調色板生成器 - 應用商店 | 免費好用的在線工具
  • 在線節拍器 - 應用商店 | 免費好用的在線工具
  • IP歸屬地查詢 - 應用商店 | 免費好用的在線工具
  • CSS網格佈局生成器 - 應用商店 | 免費好用的在線工具
  • 郵箱驗證工具 - 應用商店 | 免費好用的在線工具
  • 書法練習字帖 - 應用商店 | 免費好用的在線工具
  • 金融計算器套件 - 應用商店 | 免費好用的在線工具
  • 中國親戚關係計算器 - 應用商店 | 免費好用的在線工具
  • Protocol Buffer 工具箱 - 應用商店 | 免費好用的在線工具
  • IP歸屬地查詢 - 應用商店 | 免費好用的在線工具
  • 圖片無損放大 - 應用商店 | 免費好用的在線工具
  • 文本比較工具 - 應用商店 | 免費好用的在線工具
  • IP批量查詢工具 - 應用商店 | 免費好用的在線工具
  • 域名查詢工具 - 應用商店 | 免費好用的在線工具
  • DNS工具箱 - 應用商店 | 免費好用的在線工具
  • 網站圖標生成器 - 應用商店 | 免費好用的在線工具
  • XML Sitemap

</details>

user avatar greatsql Avatar xyjzfx Avatar Rocokingdom2024 Avatar zyx178 Avatar menglihuaxiangbian Avatar
Favorites 5 users favorite the story!
Favorites

Add a new Comments

Some HTML is okay.