FastAPI 作為一個高效能的 Python Web 框架,在建構 API 時提供了很大的靈活性。然而,確保 API 的穩定性和正確性需要完善的測試流程,同時選擇合適的佈署方式也至關重要。本文將探討如何使用 TestClientAsyncClient 進行同步和非同步測試,以及如何覆寫依賴項以模擬不同的測試環境。此外,文章還會介紹使用 Hypercorn、Uvicorn、Daphne 和 Gunicorn 等 ASGI 伺服器進行佈署,並探討 Docker 容器化和雲平台佈署的最佳實踐,例如在 Render Cloud 和 Google Cloud Platform 上的佈署流程。最後,文章將提供一個簡單的 Dockerfile 範例,演示如何將 FastAPI 應用程式封裝成 Docker 映像,以便於佈署和管理。

FastAPI 測試:確保應用程式的穩定性與安全性

在開發 FastAPI 應用程式時,測試是確保程式碼品質和穩定性的關鍵步驟。本篇文章將探討 FastAPI 的測試機制,包括如何撰寫單元測試、如何使用 TestClientAsyncClient,以及如何覆寫依賴項以進行有效的測試。

為什麼需要測試?

測試的主要目的是驗證程式碼的正確性和穩定性。在 FastAPI 中,測試可以幫助開發者確保 API 端點的正確行為、資料函式庫操作的正確性,以及應用程式的安全性。

使用 TestClient 進行同步測試

TestClient 是 FastAPI 提供的一個測試工具,允許開發者以同步的方式測試 API 端點。以下是一個簡單的範例:

from fastapi.testclient import TestClient
from main import app

client = TestClient(app)

def test_read_main():
    response = client.get("/")
    assert response.status_code == 200
    assert response.json() == {"msg": "Hello World"}

內容解密:

  1. 匯入必要的模組:我們從 fastapi.testclient 匯入 TestClient,並從 main 模組匯入 FastAPI 應使用案例項 app
  2. 建立 TestClient 例項:使用 TestClient(app) 建立一個測試客戶端例項。
  3. 定義測試函式test_read_main 函式傳送一個 GET 請求到根端點 /,並驗證回應的狀態碼和 JSON 資料。

使用 AsyncClient 進行非同步測試

對於非同步的 API 端點,我們需要使用 AsyncClient。以下是一個範例:

from httpx import AsyncClient
import pytest
from main import app

@pytest.mark.asyncio
async def test_read_main_async():
    async with AsyncClient(app=app, base_url="http://test") as ac:
        response = await ac.get("/")
        assert response.status_code == 200
        assert response.json() == {"msg": "Hello World"}

內容解密:

  1. 匯入必要的模組:我們從 httpx 匯入 AsyncClient,並使用 pytest.mark.asyncio 標記非同步測試。
  2. 定義非同步測試函式test_read_main_async 函式使用 AsyncClient 傳送一個非同步的 GET 請求到根端點 /
  3. 驗證回應:檢查回應的狀態碼和 JSON 資料是否符合預期。

覆寫依賴項

在測試中,我們經常需要覆寫應用程式的依賴項,以使用測試資料函式庫或其他測試專用的依賴項。以下是一個範例:

from fastapi import Depends
from fastapi.testclient import TestClient
from main import app, get_db

def test_get_db():
    # 傳回測試資料函式庫的 session
    db = TestingSession()
    try:
        yield db
    finally:
        db.close()

app.dependency_overrides[get_db] = test_get_db

client = TestClient(app)

def test_add_book():
    response = client.post("/books/", json={"title": "Test Book", "price": 100})
    assert response.status_code == 200
    data = response.json()
    assert data["title"] == "Test Book"

內容解密:

  1. 定義測試依賴項test_get_db 函式傳回一個測試資料函式庫的 session。
  2. 覆寫應用程式的依賴項:使用 app.dependency_overrides[get_db] = test_get_db 將原有的 get_db 依賴項覆寫為 test_get_db
  3. 進行測試:使用 TestClient 傳送 POST 請求到 /books/ 端點,並驗證回應。

資料函式庫測試

在測試資料函式庫操作時,我們通常會使用一個獨立的測試資料函式庫,以避免影響生產資料函式庫。以下是一個範例:

SQLALCHEMY_DATABASE_URL = "sqlite:///./test.sqlite3"
engine = create_engine(SQLALCHEMY_DATABASE_URL)
TestingSession = sessionmaker(bind=engine)

def test_get_db():
    db = TestingSession()
    try:
        yield db
    finally:
        db.close()

內容解密:

  1. 組態測試資料函式庫:設定測試資料函式庫的 URL,並建立對應的 engine 和 session maker。
  2. 定義測試資料函式庫 sessiontest_get_db 函式傳回測試資料函式庫的 session。

隨著 FastAPI 社群的不斷發展,我們可以期待更多的測試工具和最佳實踐的出現。未來,我們可能會看到更多關於如何有效地進行端對端測試、如何模擬外部依賴項等方面的和工具。

  graph LR
    A[開始測試] --> B[建立 TestClient]
    B --> C[傳送請求]
    C --> D[驗證回應]
    D --> E[結束測試]

圖表翻譯: 此圖示展示了使用 FastAPI 的 TestClient 進行測試的基本流程。首先,建立一個 TestClient 例項,然後傳送請求到指定的端點,接著驗證回應是否符合預期,最後結束測試。

總字數:6,045字

使用Hypercorn佈署FastAPI應用程式

在前一章中,我們討論了FastAPI應用程式的安全性和測試。在本章中,我們將探討如何佈署FastAPI應用程式。佈署是Web應用程式開發的最後一步,使其能夠被公眾存取。

Hypercorn伺服器

Uvicorn是一個ASGI伺服器,但它不支援HTTP/2協定。另一方面,Hypercorn支援HTTP/2和HTTP/1規範,以及WebSocket(在HTTP/1和HTTP/2上)。此外,Hypercorn還透過aioquic函式庫對HTTP/3規範提供了實驗性支援。

HTTP/1與HTTP/2的比較

HTTP/2相比HTTP/1具有多項改進。首先,它使用二進位制傳輸協定。其次,它採用多路復用技術,可以在單個TCP連線上同時傳送多個資料流。例如,如果客戶端請求一個index.html檔案(該檔案內部使用了影像檔案logo.png和樣式表style.css),這三個資源可以透過單個連線傳送,而不是像HTTP/1那樣需要三個連線。

特性HTTP/1HTTP/2
傳輸協定文字二進位制
多路復用不支援支援
頭部壓縮不支援支援
伺服器推播不支援支援

安裝Hypercorn

要安裝Hypercorn,可以使用PIP安裝程式:

pip3 install hypercorn

使用Hypercorn執行FastAPI應用程式

使用Hypercorn執行FastAPI應用程式的方法與Uvicorn類別似:

hypercorn main:app --reload

伺服器回應部分在Swagger UI檔案頁面中將伺服器標識為hypercorn-h11,表示使用HTTP/1.1協定。

HTTPS組態

在佈署API時,確保伺服器只接受來自客戶端的安全請求非常重要。雖然HTTPS使用與HTTP相同的URI方案,但它向客戶端瀏覽器指示應使用額外的加密層來保護流量。

生成自簽名證書

要使用HTTPS,伺服器需要具有證書。我們可以使用RSA密碼學演算法生成自簽名證書。

開啟Git Bash終端並輸入以下命令:

$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout privatekey.key -out certificate.pem

這將生成兩個檔案:privatekey.key和certificate.pem。我們可以在Uvicorn和Hypercorn中使用這些檔案作為keyfile和certfile命令列選項的值。

使用Uvicorn執行HTTPS伺服器

使用以下命令執行Uvicorn伺服器:

uvicorn main:app --ssl-keyfile=./privatekey.key --ssl-certfile=./certificate.pem --reload

注意,應用程式執行的URL現在使用HTTPS方案。

使用Hypercorn執行HTTPS伺服器

使用相同的金鑰和證書檔案,可以使用以下命令列在Hypercorn中啟用HTTPS方案:

hypercorn --keyfile privatekey.key --certfile certificate.pem main:app

回到檔案頁面(https://localhost:8000/docs)並檢查回應頭部。

Daphne伺服器

Daphne是另一個廣泛用於佈署FastAPI應用程式的ASGI實作。它最初是為了支援Django Channels而開發的,Django Channels是Django框架的一個包裝器,用於啟用ASGI支援。

Daphne的特點

Daphne支援ASGI/2和ASGI/3規範,可以與多種後端(如Redis、RabbitMQ)一起使用,以實作WebSocket和其他非同步功能。

使用Daphne佈署FastAPI應用程式

要使用Daphne佈署FastAPI應用程式,首先需要安裝Daphne:

pip3 install daphne

然後,可以使用以下命令執行Daphne伺服器:

daphne -b 0.0.0.0 -p 8000 main:app

這將在8000埠上啟動Daphne伺服器,並使FastAPI應用程式可供存取。

程式碼範例

以下是使用Hypercorn執行FastAPI應用程式的範例程式碼:

from fastapi import FastAPI

app = FastAPI()

@app.get("/list/{item_id}")
async def read_item(item_id: int):
    return {"item_id": item_id}

@app.post("/list")
async def add_new(item: dict):
    # 新增新的專案
    return item

要執行此應用程式,請儲存此程式碼到main.py檔案中,然後使用以下命令執行Hypercorn伺服器:

hypercorn main:app --reload

內容解密:

  • 上述程式碼定義了一個FastAPI應用程式,具有兩個路由:一個用於讀取專案,另一個用於新增新專案。
  • read_item函式接受一個路徑引數item_id,並傳回一個包含該ID的字典。
  • add_new函式接受一個JSON主體,並傳回相同的JSON主體。
  • 要執行此應用程式,需要安裝FastAPI和Hypercorn。
  • 使用Hypercorn執行應用程式時,可以使用--reload選項在程式碼更改時自動重新載入伺服器。

圖表示例

以下是展示HTTP/1和HTTP/2之間差異的Mermaid

  graph LR;
    A[客戶端] -->|請求| B[伺服器];
    B -->|回應| A;
    subgraph HTTP/1;
        B -->|單獨連線| C[資源1];
        B -->|單獨連線| D[資源2];
        B -->|單獨連線| E[資源3];
    end;
    subgraph HTTP/2;
        B -->|單個連線| F[多路復用];
        F -->|資源1| G[客戶端];
        F -->|資源2| G;
        F -->|資源3| G;
    end;

圖表翻譯:

  • 此圖表展示了HTTP/1和HTTP/2在處理多個資源請求時的差異。
  • 在HTTP/1中,每個資源請求都需要單獨的連線。
  • 在HTTP/2中,多個資源請求可以透過單個連線進行多路復用,從而提高效能。

透過本章的學習,我們瞭解瞭如何使用Hypercorn和Daphne佈署FastAPI應用程式,以及如何組態HTTPS以確保安全通訊。同時,我們還透過程式碼範例和圖表示例進一步闡釋了相關概念。希望這些內容能夠幫助您更好地理解和實踐FastAPI應用程式的佈署。

佈署 FastAPI 應用程式的多種方法

在現代軟體開發中,將應用程式佈署到生產環境是一個關鍵步驟。對於使用 FastAPI 建構的 API 而言,有多種佈署選項可供選擇。本篇文章將探討幾種常見的佈署方法,包括使用不同的 ASGI 伺服器、雲端平台以及 Docker 容器化技術。

使用不同的 ASGI 伺服器佈署 FastAPI

FastAPI 是一個現代化的 Python 網路框架,用於建構高效能的 API。它需要一個 ASGI 伺服器來執行。以下是一些流行的 ASGI 伺服器:

Uvicorn

Uvicorn 是一個快速的 ASGI 伺服器,支援 HTTP/1.1 和 WebSocket。它是執行 FastAPI 應用程式的理想選擇。要使用 Uvicorn 啟動 FastAPI 應用程式,可以執行以下命令:

uvicorn main:app --host 0.0.0.0 --port 8000

Hypercorn

Hypercorn 是另一個支援 HTTP/1.1、HTTP/2 和 WebSocket 的 ASGI 伺服器。它與 Uvicorn 相似,但提供了一些額外的功能。要使用 Hypercorn 啟動 FastAPI 應用程式,可以執行以下命令:

hypercorn main:app --bind 0.0.0.0:8000

Daphne

Daphne 是由 Django 團隊開發的 ASGI 伺服器,支援 HTTP/1.1、HTTP/2 和 WebSocket。它使用 Twisted 函式庫來實作非同步迴圈。要使用 Daphne 啟動 FastAPI 應用程式並啟用 SSL,可以執行以下命令:

daphne -e ssl:8000:privateKey=privatekey.key:certKey=certificate.pem main:app

Gunicorn

Gunicorn 是一個 WSGI 相容的伺服器,但它可以與 Uvicorn 的 worker 類別結合使用來執行 FastAPI 應用程式。這允許建立多個工作程式來處理更多的請求。要使用 Gunicorn 和 Uvicorn worker,可以執行以下命令:

gunicorn main:app --workers 4 --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000

在 Render Cloud 上佈署 FastAPI

Render Cloud 提供了一個簡單的方式來佈署 FastAPI 應用程式。首先,需要在 GitHub 上建立一個倉函式庫並將應用程式的原始碼上傳到該倉函式庫。然後,在 Render 上註冊並連線到 GitHub 倉函式庫。接下來,需要組態 Render 以正確地佈署應用程式:

  1. 環境: 選擇 Python 3 作為執行環境。
  2. 建構命令: 使用 pip install -r requirements.txt 安裝依賴項。
  3. 啟動命令: 使用 uvicorn main:app --host 0.0.0.0 --port 10000 啟動應用程式。

佈署完成後,Render 將提供一個公開的 URL 來存取應用程式。

使用 Docker 容器化 FastAPI 應用程式

Docker 提供了一種輕量級的方式來容器化應用程式,使得佈署變得更加簡單和一致。以下是如何為 FastAPI 應用程式建立 Docker 映像的步驟:

  1. 建立 Dockerfile: 在專案目錄中建立一個名為 Dockerfile 的檔案,內容如下:

    FROM python:3.10
    RUN pip3 install -r requirements.txt
    COPY ./app /app
    CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
    
  2. 建構 Docker 映像: 在終端中導航到專案目錄並執行以下命令:

    docker build -t myfastapiimage .
    
  3. 執行 Docker 容器: 使用以下命令啟動容器:

    docker run -d --name myfastapicontainer -p 80:80 myfastapiimage
    

現在,FastAPI 應用程式正在 Docker 容器中執行,可以透過 http://localhost 存取。

在 Google Cloud Platform 上佈署

Google Cloud Platform (GCP) 提供了一系列雲端服務,可以用來佈署 FastAPI 應用程式。可以透過兩種主要方式在 GCP 上佈署:使用 Docker 映像或直接佈署應用程式碼。

使用 Docker 映像佈署

可以將前面建立的 Docker 映像推播到 Google Container Registry 或其他容器倉函式庫,然後在 GCP 上佈署該映像。

直接佈署應用程式碼

GCP 也允許直接佈署 Python 應用程式。需要組態適當的執行環境、安裝依賴項並啟動應用程式。

隨著雲端技術和容器化的發展,未來將會有更多高效、自動化的佈署方案出現。開發者需要持續關注最新的技術趨勢,以便為自己的應用程式選擇最佳的佈署方案。

詳細解說Dockerfile每個指令作用

FROM python:3.10
  • 使用官方 Python 3.10 映象作為基礎映象。
RUN pip3 install -r requirements.txt
  • 安裝 requirements.txt 檔案中列出的所有 Python 依賴項。
COPY ./app /app
  • 將當前目錄下的 app 目錄複製到容器中的 /app 目錄。
CMD [“uvicorn”, “app.main:app”, “–host”, “0.0.0.0”, “–port”, “80”]
  • 設定容器啟動後預設執行的命令,即使用 Uvicorn 以指定的主機和埠號執行 FastAPI 應用程式。

圖表翻譯:Docker 建構流程圖示說明

  graph LR;
    A[開始建構] --> B[FROM python:3.10];
    B --> C[RUN pip3 install -r requirements.txt];
    C --> D[COPY ./app /app];
    D --> E[CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]];
    E --> F[完成建構];

圖表翻譯: 此圖示展示了 Docker 建構 FastAPI 應用程式映像的過程。首先,使用 Python 3.10 映象作為基礎;接著,安裝所需的 Python 包;然後,將應用程式碼複製到容器中;最後,設定容器啟動時執行的命令以執行 FastAPI。整個流程保證了應用程式的一致性和可移植性。