API 設計
優秀的 API 是一份合約,你可以在不破壞依賴它的使用者的情況下進行演進。先設計合約,將資源而非動作作為模型,按照規格使用 HTTP,保持向後相容,並將安全性和可操作性設為預設值,而非事後才考慮。
此技能在工作流程層級與協定無關;規範性細節位於 references/ 中,並按需載入。
優先閱讀(始終執行)
列出 learnings/ 並閱讀每個看起來與當前任務相關的檔案 — 專案的版本控制政策、錯誤封裝格式、認證模型、命名慣例以及特定提供者的 webhook 特殊規則都存放在那裡,並會覆蓋此檔案中的預設值。如果某個學習內容與此 SKILL.md 衝突,以學習內容為準 — 請告知使用者。
取捨 — 何時嚴格執行,何時放寬
對任何具有外部或跨團隊消費者,或任何持久化狀態的 API 應用完整的規範。對於完全由你控制兩端且可以原子性變更的私有、單一消費者端點,可以放寬流程 — 但絕不能放寬安全底線(授權、輸入驗證、URL 中不含機密)。
工作流程
-
審慎選擇協定。 REST 適用於資源 CRUD 和廣泛的客戶端觸及;GraphQL 適用於客戶端需要針對圖進行靈活、客戶端定製的查詢;gRPC 適用於低延遲的內部服務間通訊。不要因為 GraphQL/gRPC 是新技術就將其設為預設。說明你的選擇及其原因。 → 驗證:你能說出消費者是誰以及為何此協定適合它。
-
以合約為優先設計。 在撰寫程式碼之前,先撰寫 OpenAPI(或 proto/SDL)規格;審查它,然後根據規格產生或手寫處理器。在 CI 中 lint 該規格(例如使用 Spectral),以便規格漂移會導致建置失敗。 → 驗證:規格存在且是唯一真相來源,而非從程式碼反向工程而來。
-
將資源(名詞)作為模型,而非動作。 資源是具有身份的事物;集合使用複數形式。不常見的操作應成為子資源或狀態,而非路徑中的動詞。請參閱
references/rest-conventions.md。 → 驗證:任何路徑中都沒有動詞。 -
正確使用 HTTP 方法 + 狀態碼語意。 GET/HEAD 安全且冪等,PUT/DELETE 冪等,PATCH 部分更新,POST 建立/非冪等。狀態碼承載結果;請求主體承載資料或錯誤。請參閱
references/rest-conventions.md。 → 驗證:沒有200 OK但主體中包含錯誤的情況。 -
在所有地方應用一致的慣例。 路徑使用一種大小寫,欄位使用一種;集合使用複數;使用不透明 ID(不要洩漏資料庫序號/結構)。不一致是對每個消費者永久性的稅收。 → 驗證:讀者能夠預測他們未曾見過的端點的形狀。
-
絕不破壞消費者。 在一個版本內僅進行新增性變更;破壞性變更需要新版本和一個棄用視窗,並附帶
Deprecation/Sunset標頭。為先前無分頁的清單添加分頁是一項破壞性變更。請參閱references/versioning-and-compatibility.md。 → 驗證:在交付之前,每個變更都被分類為新增性或破壞性。 -
標準化錯誤。 使用 RFC 9457
application/problem+json搭配穩定的機器可讀code。HTTP 狀態碼必須與主體相符。絕不洩漏堆疊追蹤。請參閱references/errors-idempotency-concurrency.md。 → 驗證:每個錯誤路徑都返回相同的封裝格式和穩定的 code。 -
從第一天起就對每個清單進行分頁。 優先使用基於游標的分頁(
page_size+page_token/next連結)而非偏移量。事後再添加分頁會破壞客戶端。 → 驗證:不存在無限制的清單端點。 -
讓寫入操作可安全重試。 為非冪等的 POST 使用
Idempotency-Key(儲存並重播第一次的回應);使用ETag+If-Match實現樂觀鎖定,衝突時返回412。請參閱references/errors-idempotency-concurrency.md。 → 驗證:在逾時後重試 POST 的客戶端不會重複扣款/重複建立。 -
預設安全。 僅使用 TLS;在伺服器端驗證令牌;進行每個物件的授權(不僅是角色);URL 中不含機密;根據 schema 驗證輸入;速率限制;CORS 允許清單。請參閱
references/security.md。 → 驗證:對於每個命名物件的請求,都檢查了物件層級的授權。 -
擷取學習內容(最後一步)。 如果你遇到此檔案或
references/中尚未包含的慣例、約束或陷阱,請追加一個learnings/YYYY-MM-DD-slug.md。否則跳過。
反模式(一見即拒)
- 路徑中包含動詞 —
POST /createUser、/getOrders。請使用POST /users、GET /orders。 200 OK但主體中包含錯誤。 狀態碼即結果;客戶端和代理依賴於它。- 洩漏內部/資料庫模型 — 將欄位名稱、內部列舉、序號 ID 或連接結構暴露為公開形狀。應對應到審慎設計的 DTO。
- 過多往返 / N+1 — 強迫客戶端進行多次往返來組裝一個檢視。提供擴展功能(
expand=) 或更粗粒度的資源。 - 未使用新版本的破壞性變更 — 包括重新命名/移除欄位、變更型別或預設值,或為先前無分頁的清單添加分頁。
- 不一致的慣例 — 混合大小寫、單數與複數集合混雜、有時包裝回應有時不包裝。
- 非冪等 POST 沒有冪等金鑰 — 任何重試都會重複建立。
- URL 中包含敏感資料 — 令牌、PII、機密在路徑或查詢中;它們會進入日誌、歷史記錄和參照來源。
- 遺漏物件層級授權(BOLA) — 檢查了認證但未檢查此呼叫者是否可以存取此物件。OWASP API 第一號風險。
- 暴露堆疊追蹤 — 內部類別名稱、檔案路徑、SQL 出現在錯誤主體中。
- 無限制的清單端點 —
GET /events返回所有內容。
擷取學習內容
完成後,問自己:我是否遇到了此 SKILL.md 或 references/ 中未包含的慣例、約束或陷阱?(例如專案特定的版本控制政策、組織已標準化的非標準錯誤封裝格式、webhook 提供者的簽章方案、強制要求的標頭。)如果是,請按照 learnings/README.md 的格式追加一個 learnings/YYYY-MM-DD-slug.md。如果否,則跳過 — 不要寫入無意義的內容。
另請參閱
references/rest-conventions.md— 資源建模、命名、方法、狀態碼、分頁、過濾、快取。references/versioning-and-compatibility.md— 版本控制策略、新增性與破壞性變更、棄用政策。references/errors-idempotency-concurrency.md— problem+json、冪等金鑰、樂觀鎖定、重試、長時間運行操作、webhook。references/security.md— TLS、OAuth2/OIDC、BOLA/BFLA、輸入驗證、速率限制、CORS、資料暴露。developing-features技能 — 一般生產規則和完整安全參考(API 表面是幾個邊界之一)。reviewing-code技能 — 審查變更 API 表面的 diff。documenting-features技能 — 在程式碼旁擷取 API 合約、ADR 和領域模型。learnings/— 隨著時間累積的專案特定 API 慣例。