API 設計
在實作之前先設計合約。
使用時機
當使用者:
- 設計新的 API 或介面;
- 修改現有的合約;
- 定義請求/回應 schema;
- 審查錯誤處理、認證、分頁或版本控制;
- 與第三方服務整合;
- 詢問「這個端點應該長什麼樣子?」。
1. 釐清合約
確認:
- 誰呼叫 API:前端、行動端、服務、合作夥伴、代理;
- 呼叫者需要完成什麼;
- 資料輸入和輸出為何;
- 呼叫者絕對不能看到什麼;
- 延遲、流量和可靠性的要求;
- 相容性和版本控制限制。
2. 為資源和操作建立模型
- 使用名詞表示資源,使用明確的動詞表示非 CRUD 的操作。
- 保持 URL 穩定且可預測。
- 偏好一種明確的方式來完成一件事。
- 避免將資料庫結構洩漏到公開合約中。
- 定義識別碼、擁有權和租戶。
3. 定義 Schema
對於每個端點或介面:
- 方法和路徑;
- 目的;
- 認證和權限;
- 路徑、查詢和主體參數;
- 驗證規則;
- 成功回應;
- 錯誤回應;
- 冪等性;
- 分頁;
- 速率限制;
- 範例。
4. 設計錯誤
每個錯誤應包含:
- 穩定的機器可讀代碼;
- 人類可讀的訊息;
- 導致錯誤的欄位或參數;
- 用於支援的請求 ID;
- 不包含堆疊追蹤、機密或內部路徑。
使用一致的 HTTP 狀態碼。不要為失敗的操作返回 200。
5. 安全性與隱私
- 對每個非公開端點進行認證。
- 在物件層級授權,而不僅僅在路由層級。
- 在邊界驗證所有輸入。
- 只返回呼叫者需要的欄位。
- 如果內部 ID 會洩漏資訊,請勿暴露它們。
- 定義速率限制和濫用控制。
- 將 Webhook 視為不可信的輸入。
6. 可演化性
- 添加欄位,而不是改變其含義。
- 在用戶端遷移之前保留舊欄位。
- 只在必要時進行版本控制。
- 記錄棄用和遷移。
- 避免在小版本中引入破壞性變更。
7. 輸出格式
## 合約
### `METHOD /path`
**目的:** <它的功能>
**認證:** <誰可以呼叫它>
**冪等性:** <是/否及金鑰>
#### 請求
| 欄位 | 類型 | 必填 | 規則 |
|---|---|---|---|
#### 回應
```json
{}
```
#### 錯誤
| 狀態碼 | 代碼 | 發生時機 |
|---|---|---|
#### 範例
```http
METHOD /path
...
```
## 相容性
- <可以變更的項目>
- <需要新版本的項目>
## 待確認問題
- <問題>
規則
- 不要發明業務規則。
- 不要在沒有理由的情況下暴露內部欄位。
- 不要在端點之間使用不一致的命名。
- 不要圍繞當前的資料庫 schema 設計公開 API。
- 不要忽略錯誤和空狀態的行為。
- 如果 API 處理金錢、健康或個人資料,則需要進行安全審查。
品質檢查
- 呼叫者和任務是明確的。
- Schema 是完整的。
- 錯誤是一致且安全的。
- 已定義認證和物件層級權限。
- 已定義分頁和限制。
- 已處理相容性問題。
- 範例是有效的。