FastAPI 物件建立與設定(Application Setup)
簡介
在使用 FastAPI 建立 API 時,最先要面對的就是「應用程式的結構與啟動方式」。
一個清晰、可維護的應用程式架構不僅能提升開發效率,也能讓日後的測試、部署與擴充變得更簡單。
本單元將從 FastAPI 物件的建立、路由、Middleware、依賴注入 以及 設定管理 四大要素切入,說明如何在程式碼層面完成基礎建置,並提供實務範例與常見陷阱,幫助初學者快速上手,同時讓中階開發者也能在大型專案中落實最佳實踐。
核心概念
1️⃣ 建立 FastAPI 物件
FastAPI 的入口就是 FastAPI() 類別的實例。它會自動產生 OpenAPI 文件、Swagger UI、Redoc 等工具,只要正確建立即可直接使用。
from fastapi import FastAPI
# 建立應用程式實例
app = FastAPI(
title="My Awesome API",
description="示範 FastAPI 基礎設定",
version="1.0.0",
# 下面的參數可自行調整
docs_url="/docs", # Swagger UI
redoc_url="/redoc", # ReDoc
openapi_url="/openapi.json"
)
# 簡單的測試路由
@app.get("/ping")
async def ping() -> str:
"""健康檢查端點,回傳字串 'pong'。"""
return "pong"
重點:
FastAPI()只需要在專案的入口檔(如main.py)建立一次,之後所有路由、Middleware、事件等都會掛載在這個實例上。
2️⃣ 使用 APIRouter 進行模組化
隨著 API 功能增多,直接在 main.py 中寫大量路由會變得雜亂。FastAPI 提供 APIRouter 讓我們把相關路由分散到不同檔案,最後在主應用程式中統一註冊。
# routers/users.py
from fastapi import APIRouter, HTTPException
router = APIRouter(
prefix="/users",
tags=["users"], # Swagger UI 中的分組標籤
responses={404: {"description": "Not found"}}
)
# 假資料
fake_users_db = {"alice": {"name": "Alice", "age": 30}}
@router.get("/{username}")
async def read_user(username: str):
"""取得單一使用者資訊。"""
user = fake_users_db.get(username)
if not user:
raise HTTPException(status_code=404, detail="User not found")
return user
# main.py
from fastapi import FastAPI
from routers import users # 只要在 __init__.py 中匯出即可
app = FastAPI()
# 將 router 註冊到主應用程式
app.include_router(users.router)
技巧:使用
tags、prefix、responses等參數,能讓自動產生的 API 文件更具可讀性。
3️⃣ Middleware:跨請求的前後處理
Middleware 允許在每一次請求進入或離開時執行自訂程式碼,常見用途包括 CORS、日誌、驗證 等。
# middlewares/logging.py
import time
from fastapi import Request
from starlette.middleware.base import BaseHTTPMiddleware
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) * 1000
# 記錄簡易日誌
print(f"{request.method} {request.url.path} - {response.status_code} "
f"({process_time:.2f}ms)")
return response
# main.py
from fastapi import FastAPI
from middlewares.logging import LoggingMiddleware
app = FastAPI()
app.add_middleware(LoggingMiddleware)
注意:
BaseHTTPMiddleware會把 同步 與 非同步 的呼叫都包裝成協程,若需要更高效能,可直接使用starlette.middleware中的原始類別。
4️⃣ 依賴注入(Dependency Injection)
FastAPI 的依賴系統讓我們可以把 資料庫連線、驗證、設定檔 等重複使用的資源抽離成函式,然後在路由或其他依賴中「注入」它們。
# dependencies.py
from fastapi import Depends, Header, HTTPException
async def verify_token(x_token: str = Header(...)):
"""簡易的 Token 驗證依賴。"""
if x_token != "secret-token":
raise HTTPException(status_code=401, detail="Invalid token")
return x_token
async def get_query_param(q: str = None):
"""取得查詢參數,若未提供則回傳預設值。"""
return q or "default"
# main.py
from fastapi import FastAPI, Depends
from dependencies import verify_token, get_query_param
app = FastAPI()
@app.get("/protected")
async def protected_route(token: str = Depends(verify_token)):
"""只有通過 verify_token 的請求才能取得此資源。"""
return {"msg": "Access granted", "token": token}
@app.get("/search")
async def search(q: str = Depends(get_query_param)):
"""示範使用 Depends 注入查詢參數。"""
return {"query": q}
重點:
Depends可以嵌套使用,形成 依賴樹,非常適合在大型專案中統一管理認證、資料庫會話等資源。
5️⃣ 設定管理(Settings)
在實務開發中,我們常需要根據 環境變數 或 設定檔 來調整資料庫連線、API 金鑰等。pydantic 提供的 BaseSettings 能自動讀取環境變數,且支援型別檢查。
# config.py
from pydantic import BaseSettings, Field
class Settings(BaseSettings):
app_name: str = Field(..., env="APP_NAME")
debug: bool = Field(False, env="DEBUG")
db_url: str = Field(..., env="DATABASE_URL")
secret_key: str = Field(..., env="SECRET_KEY")
class Config:
env_file = ".env" # 讀取 .env 檔案
# 取得全域設定物件
settings = Settings()
# main.py
from fastapi import FastAPI
from config import settings
app = FastAPI(title=settings.app_name, debug=settings.debug)
@app.get("/info")
async def info():
"""回傳目前的設定資訊(僅示範,實務上要注意隱私)。"""
return {
"app_name": settings.app_name,
"debug": settings.debug,
"db_url": settings.db_url
}
實務建議:絕對不要 把機密資訊直接寫在程式碼中,務必透過環境變數或安全的密鑰管理服務注入。
常見陷阱與最佳實踐
| 常見陷阱 | 為什麼會發生 | 解決方式/最佳實踐 |
|---|---|---|
在 main.py 直接寫大量路由 |
隨著功能增長,檔案變得難以閱讀、測試困難。 | 使用 APIRouter 模組化,並在 app.include_router() 中統一掛載。 |
| Middleware 中使用阻塞 I/O | 會阻塞事件迴圈,導致整體效能下降。 | 儘量使用 非同步 I/O,或在需要阻塞時使用 run_in_threadpool。 |
| 依賴注入函式產生大量資料庫連線 | 每次請求都會重新建立連線,資源浪費。 | 使用 Depends 搭配 yield(即 @contextmanager)在請求結束後關閉連線,或使用連線池。 |
| 設定檔硬編碼 | 部署到不同環境(dev、staging、prod)時需改動程式碼。 | 以 .env、環境變數 或 設定服務(如 AWS Parameter Store)管理設定。 |
| 未設定 CORS | 前端跨域請求會被瀏覽器阻擋。 | 加入 CORSMiddleware,僅允許可信任的來源。 |
| 過度使用全域變數 | 會在測試或多執行緒環境下產生資料競爭。 | 盡量把狀態封裝在 依賴 或 class instance 中。 |
小技巧
- 自動產生 OpenAPI 文件:只要在
FastAPI()建構子裡設定title、description、version,Swagger UI 會即時更新。 - 使用
lifespan事件:可在應用啟動與關閉時執行一次性程式(如連接資料庫、關閉資源)。 - 測試友好:把
app物件放在可被 import 的模組,讓TestClient能直接引用。
# app.py
from fastapi import FastAPI
def create_app() -> FastAPI:
app = FastAPI()
# 這裡加入 router、middleware、事件等
return app
app = create_app()
# test_main.py
from fastapi.testclient import TestClient
from app import create_app
client = TestClient(create_app())
def test_ping():
response = client.get("/ping")
assert response.status_code == 200
assert response.json() == "pong"
實際應用場景
| 場景 | 需求 | 建議的設定方式 |
|---|---|---|
| 微服務 API | 每個服務都有獨立的設定、需要快速部署 | 使用 BaseSettings 搭配 Docker 環境變數,將 app = FastAPI() 包裝成 create_app() 函式,方便 CI/CD。 |
| 企業內部系統 | 需要統一的認證、日誌、錯誤處理 | 在 main.py 加入全局 LoggingMiddleware、CORSMiddleware,並透過 Depends 注入 verify_token,所有路由共享。 |
| 資料分析平台 | 大量的背景任務(如批次匯入)與 API 並存 | 使用 BackgroundTasks 或 Celery,將任務排程與 API 分開;在 FastAPI 中只負責請求驗證與回傳結果。 |
| 多語系前端 | 前端根據 Accept-Language 需求返回不同語系訊息 |
建立 LocaleDependency,在每個路由使用 Depends 取得語系,並在回傳的 JSON 中加入 message 欄位。 |
總結
- FastAPI 物件(
FastAPI())是整個應用的核心,只需要建立一次即可。 - 使用 APIRouter 讓路由模組化,提升可讀性與測試性。
- Middleware 為跨請求的前後處理提供便利,請注意非同步與阻塞的差異。
- 依賴注入 讓認證、資料庫、設定等資源可以統一管理,避免重複程式碼。
- 設定管理 建議使用
pydantic.BaseSettings搭配環境變數,確保部署彈性與安全性。 - 避免常見陷阱,遵守最佳實踐,能讓你的 FastAPI 應用在 開發、測試、部署 各階段都保持高效、可靠。
掌握了本單元的概念與實作,你就能快速建立 結構清晰、可擴充、易測試 的 FastAPI 專案,為後續的業務邏輯與資料處理奠定堅實基礎。祝開發順利! 🚀