本文 AI 產出,尚未審核

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)

技巧:使用 tagsprefixresponses 等參數,能讓自動產生的 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() 建構子裡設定 titledescriptionversion,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 加入全局 LoggingMiddlewareCORSMiddleware,並透過 Depends 注入 verify_token,所有路由共享。
資料分析平台 大量的背景任務(如批次匯入)與 API 並存 使用 BackgroundTasks 或 Celery,將任務排程與 API 分開;在 FastAPI 中只負責請求驗證與回傳結果。
多語系前端 前端根據 Accept-Language 需求返回不同語系訊息 建立 LocaleDependency,在每個路由使用 Depends 取得語系,並在回傳的 JSON 中加入 message 欄位。

總結

  • FastAPI 物件FastAPI())是整個應用的核心,只需要建立一次即可。
  • 使用 APIRouter 讓路由模組化,提升可讀性與測試性。
  • Middleware 為跨請求的前後處理提供便利,請注意非同步與阻塞的差異。
  • 依賴注入 讓認證、資料庫、設定等資源可以統一管理,避免重複程式碼。
  • 設定管理 建議使用 pydantic.BaseSettings 搭配環境變數,確保部署彈性與安全性。
  • 避免常見陷阱,遵守最佳實踐,能讓你的 FastAPI 應用在 開發、測試、部署 各階段都保持高效、可靠。

掌握了本單元的概念與實作,你就能快速建立 結構清晰、可擴充、易測試 的 FastAPI 專案,為後續的業務邏輯與資料處理奠定堅實基礎。祝開發順利! 🚀