FastAPI Request Header 與 Cookie 參數
除了 URL 路徑、查詢字串和 Request Body 之外,HTTP 請求中還包含了 Header (標頭) 和 Cookie。
FastAPI 提供了 Header 和 Cookie 類別,用法與 Query 和 Path 非常相似。
Header 參數
要讀取 Header,你需要從 fastapi 匯入 Header。
from typing import Annotated
from fastapi import FastAPI, Header
app = FastAPI()
@app.get("/items/")
async def read_items(user_agent: Annotated[str | None, Header()] = None):
return {"User-Agent": user_agent}
自動轉換 (Underscore to Hyphen)
HTTP Header 通常包含連字號 (如 User-Agent),但在 Python 變數命名中我們使用底線 (user_agent)。
預設情況下,Header 會聰明地將參數名稱中的底線 _ 轉換為連字號 - 去讀取對應的 Header。
也就是說,當你宣告 user_agent 時,FastAPI 會去讀取 User-Agent Header。
如果你不想啟用這個自動轉換功能 (例如你的 Header 真的就有底線),可以設定 convert_underscores=False:
@app.get("/items/")
async def read_items(
strange_header: Optional[str] = Header(None, convert_underscores=False)
):
return {"strange_header": strange_header}
重複的 Header
如果一個 Header 出現多次 (例如 X-Token: foo 和 X-Token: bar),你可以將型別宣告為 List[str] 來接收所有值。
from typing import List
@app.get("/items/")
async def read_items(x_token: Optional[List[str]] = Header(None)):
return {"X-Token values": x_token}
Cookie 參數
讀取 Cookie 的方式與 Header 幾乎一模一樣,只需改用 Cookie 類別。
from typing import Annotated
from fastapi import Cookie, FastAPI
app = FastAPI()
@app.get("/items/")
async def read_items(ads_id: Annotated[str | None, Cookie()] = None):
return {"ads_id": ads_id}
注意:如果你直接宣告
ads_id: str 而沒有使用 Cookie(...) 或 Header(...),FastAPI 會把它當作 Query Parameter。所以務必明確指定。使用 Pydantic Model 讀取
當你需要同時讀取多個相關的 Header 或 Cookie 時,將它們封裝到一個 Pydantic Model 中會讓程式碼更有結構,也更容易在不同路由之間重用驗證邏輯。
讀取多個 Cookie
假設你的應用程式有多個追蹤用的 Cookie,你可以這樣定義:
from pydantic import BaseModel, ConfigDict
class CookieModel(BaseModel):
# 這裡的變數名稱必須跟 Cookie 的名稱完全一致
session_id: str
fatebook_tracker: str | None = None
goog_analytics: str | None = None
# 建議加上這個設定,防止客戶端傳送多餘的 Cookie 混淆
model_config = ConfigDict(extra="forbid")
@app.get("/items/")
async def read_items(cookies: Annotated[CookieModel, Cookie()]):
return cookies
讀取多個 Header
同樣的技巧也能用在 Header 上。這在需要驗證一整組自定義標頭時非常方便:
class CommonHeaders(BaseModel):
host: str
save_data: bool
if_modified_since: str | None = None
user_agent: str | None = None
x_token: list[str] = []
model_config = ConfigDict(extra="forbid")
@app.get("/headers/")
async def read_headers(headers: Annotated[CommonHeaders, Header()]):
return headers
為什麼要用 Pydantic Model?
- 集中管理:驗證規則(如長度、Regex)可以直接寫在 Model 欄位裡。
- 重用性:同樣的一組標頭驗證可以輕鬆應用到多個不同的 API 路由。
- 自動文件:Swagger UI 會清楚地列出 Model 中定義的所有標頭與 Cookie,並標註哪些是必填的。
- 防止多餘資料:透過
extra="forbid",你可以確保 API 嚴格只處理你定義的參數。
總結
- 使用
Header(...)讀取 HTTP 標頭。 - 使用
Cookie(...)讀取 Cookie。 Header預設會自動將變數名稱的_轉為-。- 兩者的用法與參數驗證功能皆與
Query和Path相同。