Skip to content

RESTful 筆記(附 Python FastAPI + CURL 範例)

Last Updated on 2024-06-02 by Clay

介紹

RESTful 設計風格(Representational State Transfer, REST)是一種用於設計網路應用程式的架構風格。它遵守著讓網路應用程式更加簡潔、可擴展和易於維護的準則去設計。

以下是 RESTful 設計風格的核心概念和原則:

核心概念

  1. 資源 (Resources):
    • 資源是網絡中的任何實體,可以是用戶、圖片、文件等
    • 每個資源都由一個 URI (Uniform Resource Identifier) 唯一標識
  2. 表現形式 (Representations):
    • 資源可以有多種表現形式,例如 JSON、XML、HTML 等
    • 客戶端通過這些表現形式與資源進行互動
  3. 狀態轉換 (State Transfer):
    • 客戶端與服務器之間的互動是無狀態的,每個請求都包含所有必要的信息
    • 通過 HTTP 方法(如 GET、POST、PUT、DELETE)進行狀態轉換


基本原則

  1. 無狀態 (Statelessness):
    • 每個請求都應該是獨立的,不依賴於之前的請求
    • 服務器不會在請求之間保留客戶端的狀態
  2. 統一接口 (Uniform Interface):
    • 使用標準的 HTTP 方法和狀態碼
    • 資源的表示應該是帶有意義的,以便客戶端能夠理解和使用它們
  3. 可擴展性 (Scalability):
    • 通過無狀態的請求和分層系統設計來提高系統的可擴展性
  4. 可緩存性 (Cacheability):
    • 服務器應明確標識哪些資源是可緩存的,以提高性能
  5. 分層系統 (Layered System):
    • 客戶端不需要知道直接與最終服務器通信,請求可能通過多個中介層
    • 這種分層設計有助於提高系統的可擴展性和安全性
  6. 按需編碼 (Code on Demand)(Optional):
    • 服務器可以將可執行代碼(如 JavaScript)傳遞給客戶端,讓客戶端在運行時執行


HTTP 方法

講到 RESTful 原則設計出的 APIs,就順便條列一下基本的 HTTP 請求方法:

  1. GET:
    • 用於檢索、取得資源
    • 是 read-only 操作,不會改變資源的狀態
  2. POST:
    • 用於創建新的資源
    • 通常會在服務器創建一個新資源並返回其 URI
  3. PUT:
    • 用於更新現有資源
    • 如果資源不存在,可以創建一個新的(簡單來說,跟 insert + update 組合成的 upsert 操作很像
  4. DELETE:
    • 用於刪除資源
  5. PATCH:
    • 用於部分更新資源


遵守著以上原則,基本上我們就可以設計出簡單、可擴展性、可維護性高且靈活的 APIs。接下來我們就來實際操作一次。


實際案例

以下是使用 Python FastAPI 所啟動的一個簡單的 RESTful APIs 接口,涵蓋了基本的 CRUD 操作。

from typing import List, Optional

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import uvicorn

app = FastAPI()


# Define resource model
class Item(BaseModel):
    id: int
    name: str
    description: Optional[str] = None
    price: float
    tax: Optional[float] = None


# Simulated database
items_db = []


# POST - Create resource
@app.post("/items/", response_model=Item)
def create_item(item: Item):
    for db_item in items_db:
        if db_item.id == item.id:
            raise HTTPException(status_code=400, detail="Item already exists")

    items_db.append(item)
    return item


# GET - Get the all resources
@app.get("/items/", response_model=List[Item])
def read_items():
    return items_db


# GET - Get the specific resource
@app.get("/items/{item_id}", response_model=Item)
def read_item(item_id: int):
    for item in items_db:
        if item.id == item_id:
            return item
    raise HTTPException(status_code=404, detail="Item not found")


# PUT - Update the resource
@app.put("/items/{item_id}", response_model=Item)
def update_item(item_id: int, updated_item: Item):
    for index, item in enumerate(items_db):
        if item.id == item_id:
            items_db[index] = updated_item
            return updated_item
    raise HTTPException(status_code=404, detail="Item not found")


# PUT - Update part of resource
@app.patch("/items/{item_id}", response_model=Item)
def partial_update_item(item_id: int, item_update: dict):
    for item in items_db:
        if item.id == item_id:
            if "name" in item_update:
                item.name = item_update["name"]
            if "description" in item_update:
                item.description = item_update["description"]
            if "price" in item_update:
                item.price = item_update["price"]
            if "tax" in item_update:
                item.tax = item_update["tax"]
            
            return item

    raise HTTPException(status_code=404, detail="Item not found")


# Delete - delete the resource
@app.delete("/items/{item_id}")
def delete_item(item_id: int):
    for index, item in enumerate(items_db):
        if item.id == item_id:
            del items_db[index]
            return {"detail": "Item deleted"}

    raise HTTPException(status_code=404, detail="Item not found")


if __name__ == "__main__":
    uvicorn.run("app:app", host="0.0.0.0", port=8000, reload=True)


CURL 終端機請求範例

在開啟 FastAPI 服務後,可以使用以下的 HTTP 方法去請求資源。以下的方法因為 WordPress 現在不給放完整的 curl 指令,所以我只紀錄了後段,要測試只需要在最前方加上 curl 指令即可。

創建資源 (POST)

-X POST "http://127.0.0.1:8000/items/" -H "Content-Type: application/json" -d '{"id": 1, "name": "Item1", "description": "A sample item", "price": 10.0, "tax": 1.0}'


獲取所有資源 (GET)

-X GET "http://127.0.0.1:8000/items/"


獲取單個資源 (GET)

-X GET "http://127.0.0.1:8000/items/1"


更新資源 (PUT)

-X PUT "http://127.0.0.1:8000/items/1" -H "Content-Type: application/json" -d '{"id": 1, "name": "Updated Item", "description": "Updated description", "price": 20.0, "tax": 2.0}'


部分更新資源 (PATCH)

-X PATCH "http://127.0.0.1:8000/items/1" -H "Content-Type: application/json" -d '{"name": "Partially Updated Item", "price": 15.0}'


刪除資源 (DELETE)

-X DELETE "http://127.0.0.1:8000/items/1"


這些命令展示了如何使用 curl 與 FastAPI 構建的 RESTful API 進行互動。


References


Read More

Leave a Reply