FastAPI 中間件 (Middleware)

Middleware 是一個函數,它會在每個 請求 (Request) 被特定的路徑操作處理之前,以及每個 回應 (Response) 回傳之前執行。

Middleware 位於應用程式與客戶端之間,就像一道門戶。

它可以做的事情包括:

  • 在請求到達路徑操作之前,修改請求物件 (例如:添加 Header)。
  • 在回應回傳給客戶端之前,修改回應物件。
  • 計算請求處理時間 (Process Time)。
  • 攔截錯誤。

建立 Middleware

要建立 Middleware,你需要定義一個包含 requestcall_next 參數的非同步函數,並使用 @app.middleware("http") 裝飾器。

import time
from fastapi import FastAPI, Request

app = FastAPI()

@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
    # 1. 請求處理前 (Before Request)
    start_time = time.time()

    # 2. 呼叫下一個處理流程 (可能是路徑操作,或是下一個 Middleware)
    response = await call_next(request)

    # 3. 回應處理後 (After Response)
    process_time = time.time() - start_time

    # 修改回應:加入自訂 Header
    response.headers["X-Process-Time"] = str(process_time)

    return response

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

在這個範例中:

  1. 我們記錄了開始時間。
  2. await call_next(request) 會把請求傳遞下去,直到拿到回應。
  3. 計算總共花費的時間。
  4. 將時間寫入 Response Header X-Process-Time

常用的內建 Middleware

FastAPI (實際上是 Starlette) 內建了許多好用的 Middleware。

TrustedHostMiddleware

限制只能透過特定的 Host Name (網域名稱) 存取 API,防止 HTTP Host Header 攻擊。

from fastapi.middleware.trustedhost import TrustedHostMiddleware

app = FastAPI()

app.add_middleware(
    TrustedHostMiddleware,
    allowed_hosts=["example.com", "*.example.com"],
)

GZipMiddleware

自動對回應內容進行 GZip 壓縮,減少傳輸量。

from fastapi.middleware.gzip import GZipMiddleware

app = FastAPI()

app.add_middleware(GZipMiddleware, minimum_size=1000)

HTTPSRedirectMiddleware

強制將所有 HTTP 請求重定向到 HTTPS。

from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware

app = FastAPI()

app.add_middleware(HTTPSRedirectMiddleware)

CORS Middleware

這可能是最常用的一個。由於瀏覽器的安全性限制 (同源政策),前端網頁 (如跑在 localhost:3000) 預設不能呼叫不同源的 API (如 localhost:8000)。

我們將在 CORS 文章中專門介紹如何設定 CORS。

總結

  • 使用 @app.middleware("http") 來自訂 Middleware。
  • Middleware 可以攔截並修改 Request 和 Response。
  • 利用 add_middleware 來加入現成的第三方 Middleware。