15個與語言無關的REST API設計技巧 - bluethl
在這篇文章中,我正在盡我最大的努力壓縮我所知道的關於什麼是好的 API 的一切。您的消費者會喜歡使用的 API。所有提示都與語言無關,因此它們適用於任何框架或技術。
1. 保持一致
- 對欄位、資源和引數使用相同的大小寫(我更喜歡snake_case)
- 使用複數或單數資源名稱(我更喜歡複數)
- /users/{id},/orders/{id}或/user/{id},/order/{id}
- 對所有端點使用相同的身份驗證和授權方法
- 在 API 中使用相同的 HTTP 標頭
- 例如Api-Key用於傳遞 API 金鑰
- 根據響應型別使用相同的 HTTP 狀態程式碼
- 例如404,當找不到資源時
- 對相同型別的操作使用相同的 HTTP 方法
- 例如DELETE刪除資源時
2. 使用ISO 8601 UTC 日期
在處理日期和時間時,API 應始終返回 ISO 8601 格式的字串。在特定時區顯示日期通常是客戶端應用程式關心的問題。
{ "published_at": "2022-03-03T21:59:08Z" } |
3. 對公共端點進行例外處理
預設情況下,每個端點都應該需要授權。大多數端點都需要呼叫經過身份驗證的使用者,因此將其設為預設值是有意義的。如果需要公開呼叫端點,請顯式設定此端點以允許未經授權的請求。
4.提供健康檢查端點
GET /health提供一個確定服務是否健康的端點(例如)。其他應用程式(例如負載均衡器)可以呼叫此端點以在服務中斷時採取行動。
5. 版本化 API
確保對 API 進行版本控制並在每個請求中傳遞版本,這樣消費者就不會受到對另一個版本的任何更改的影響。API 版本可以使用 HTTP 標頭或查詢/路徑引數傳遞。即使是 API 的第一個版本(1.0)也應該明確地進行版本控制。
一些例子:
- https://api.averagecompany.com/v1/health
- https://api.averagecompany.com/health?api_version=1.0
6.接受API金鑰認證
如果 API 需要由第三方呼叫,則允許透過 API 金鑰進行身份驗證是有意義的。API 金鑰應使用自定義 HTTP 標頭(例如Api-Key)傳遞。它們應該有一個到期日期,並且必須可以撤銷活動金鑰,以便在它們受到損害時可以使它們失效。避免將 API 金鑰簽入原始碼控制(改用環境變數)。
7. 使用合理的 HTTP 狀態碼
使用傳統的 HTTP 狀態程式碼來指示請求的成功或失敗。不要使用太多,並在整個 API 中為相同的結果使用相同的狀態程式碼。一些例子:
- 200取得普遍成功
- 201為成功創作
- 400對於來自客戶端的錯誤請求
- 401對於未經授權的請求
- 403缺少許可權
- 404對於缺少的資源
- 429對於太多的請求
- 5xx對於內部錯誤(應不惜一切代價避免這些錯誤)
8.使用合理的HTTP方法
HTTP 方法有很多,但最重要的是:
- POST用於建立資源
- POST /users
- GET用於閱讀資源(單個資源和集合)
- GET /users
- GET /users/{id}
- PATCH用於對資源應用部分更新
- PATCH /users/{id}
- PUT用於對資源應用完整更新(替換當前資源)
- PUT /users/{id}
- DELETE用於刪除資源
- DELETE /users/{id}
9.使用不言自明、簡單的名字
大多數端點都是面向資源的,應該這樣命名。不要新增可以從其他地方推斷出的不必要的資訊。這也適用於欄位名稱。
好:
- GET /users=> 檢索使用者
- DELETE /users/{id}=> 刪除使用者
- POST /users/{id}/notifications=> 為特定使用者建立通知
- user.first_name
- order.number
壞:
- GET /getUser
- POST /updateUser
- POST /notification/user
- order.ordernumber
- user.firstName
10. 使用標準化的錯誤響應
除了使用指示請求結果(成功或錯誤)的 HTTP 狀態程式碼外,在返回錯誤時,始終使用標準化的錯誤響應,其中包含有關問題的更詳細資訊。消費者總是可以期待相同的結構並採取相應的行動。
// Request => GET /users/4TL011ax // Response <= 404 Not Found { "code": "user/not_found", "message": "A user with the ID 4TL011ax could not be found." } // Request => POST /users { "name": "John Doe" } // Response <= 400 Bad Request { "code": "user/email_required", "message": "The parameter [email] is required." } |
11. 返回建立的資源POST
POST在使用請求建立資源後返回建立的資源是個好主意。這一點很重要,因為返回的建立資源將反映底層資料來源的當前狀態,並將包含更新的資訊(例如生成的 ID)。
// Request: POST /users { "email": "jdoe@averagecompany.com", "name": "John Doe" } // Response { "id": "T9hoBuuTL4", "email": "jdoe@averagecompany.com", "name": "John Doe" } |
12. PATCH好於PUT
如前所述,PATCH請求應該對資源應用部分更新,而PUT完全替換現有資源。
而圍繞 PATCH 請求設計更新通常是個好主意,因為:
- 當使用PUT只更新資源的一部分欄位時,仍然需要傳遞整個資源,這使得它更加網路密集且容易出錯
- 允許任何欄位不受任何限制地更新也是相當危險的
- 根據我的經驗,在實踐中幾乎不存在任何對資源進行完整更新有意義的用例
- 想象一個order資源有一個id和一個state
- 允許消費者更新state一個order
- 狀態更改更有可能由另一個端點(例如/orders/{id}/fulfill)觸發
13. 儘可能具體
如上一節所述,在設計端點、命名欄位以及決定接受哪些請求和響應時,儘可能具體是一個好主意。如果一個PATCH請求只接受兩個欄位 (name和description),則不存在錯誤使用它和損壞資料的危險。
14.使用分頁
對所有返回資源集合並使用相同響應結構的請求進行分頁。使用page_numberand page_size(或類似的)來控制要檢索的塊。
// Request => GET /users?page_number=1&page_size=15 // Response <= 200 OK { "page_number": 1, "page_size": 15, "count": 378, "data": [ // resources ], "total_pages": 26, "has_previous_page": true, "has_next_page": true } |
15.允許擴充套件資源
允許消費者使用名為expand(或類似的)查詢引數載入相關資料。這對於避免往返和一次性載入特定操作所需的所有資料特別有用。
// Request => GET /users/T9hoBuuTL4?expand=orders&expand=orders.items // Response <= 200 OK { "id": "T9hoBuuTL4", "email": "jdoe@averagecompany.com", "name": "John Doe", "orders": [ { "id": "Hy3SSXU1PF", "items": [ { "name": "API course" }, { "name": "iPhone 13" } ] }, { "id": "bx1zKmJLI6", "items": [ { "name": "SaaS subscription" } ] } ] } |
相關文章
- 13 個設計 REST API 的最佳實踐RESTAPI
- 【語言】Java 日期 API 的使用技巧JavaAPI
- rest-api設計風格RESTAPI
- Django REST framework API 指南(15):限流DjangoRESTFrameworkAPI
- 如何提高函數語言程式設計技巧函數程式設計
- 符合語言習慣的 Python 優雅程式設計技巧Python程式設計
- 學寫PEP,參與Python語言的設計Python
- Battleship程式設計語言與技術BAT程式設計
- 函數語言程式設計的幾個概念函數程式設計
- 【線上報表設計】提升報表外觀的15個技巧
- Python學習中:最感到驚奇35個語言特徵和程式設計技巧Python特徵程式設計
- JavaScript 函數語言程式設計技巧 - 反柯里化JavaScript函數程式設計
- 30秒無需編碼完成一個REST API服務RESTAPI
- 使用C語言程式設計的7個步驟C語言程式設計
- JavaScript函數語言程式設計無痛入門JavaScript函數程式設計
- 改變遊戲規則的 API 設計審查的5個技巧遊戲API
- 快速掌握Java8 Stream函數語言程式設計技巧Java函數程式設計
- JDK 8 新特性之函數語言程式設計 → Stream APIJDK函數程式設計API
- rest apiRESTAPI
- C語言的幾個關鍵字C語言
- L1-003 個位數統計 (15分)(chen-c語言)C語言
- Python函數語言程式設計系列001:無副作用Python函數程式設計
- 21個UI設計必會的設計技巧UI
- go語言json的使用技巧GoJSON
- 計算機程式語言的分類,解釋型語言、編譯型語言、指令碼語言的關係計算機編譯指令碼
- Go語言 | 併發設計中的同步鎖與waitgroup用法GoAI
- JavaScript函數語言程式設計之pointfree與宣告式程式設計JavaScript函數程式設計
- 從語言設計的角度探究Java中hashCode()和equals()的關係Java
- GraphQL API vs REST APIAPIREST
- [譯]使用 JavaScript 物件 Rest 和 Spread 的7個技巧JavaScript物件REST
- 淺談函數語言程式設計與 Java Stream函數程式設計Java
- 高階程式語言設計第八個個人作業
- 程式語言設計,程式設計哲學程式設計
- 關於多賬套API的設計API
- Vivado使用技巧(15):DRC設計規則檢查
- RAC的函數語言程式設計函數程式設計
- 因 AI 而設計的語言 LISPAILisp
- 構建API的7個技巧API