REST簡介
在2000年,羅伊·菲爾德(Roy Fielding)提出了代表性狀态轉移(REST)作為設計Web服務的體系結構方法。REST是一種用于建構基于超媒體的分布式系統的體系結構樣式。REST獨立于任何底層協定,不一定與HTTP綁定。但是,大多數常見的REST實作使用HTTP作為應用程式協定,并且本指南重點介紹為HTTP設計REST API。
使用HTTP的RESTful API的一些主要設計原則
URL設計
避免在URI中使用動詞,應該采用“動詞 + 名詞”的設計結構。這是因為HTTP動詞應足以描述對資源執行的操作。
比如,GET /articles這個指令,GET是動詞,/articles是名詞。可以解釋為:擷取全部或者
使用标準HTTP動詞對資源執行操作有:
- GET:讀取(Read)
- POST:建立(Create)
- PUT:更新(Update)
- PATCH:更新(Update),通常是部分更新
- DELETE:删除(Delete)
傳回格式設計
- 不要傳回純文字,應該使用JSON作為資料格式,注意這裡不是json字元串,而是json對象,是以http header的Content-Type屬性要設為application/json
- 用戶端請求時,也要明确告訴伺服器,可以接受 JSON 格式,即請求的 HTTP 頭的ACCEPT屬性也要設成application/json
使用複數名詞
既然 URL 是名詞,那麼應該使用複數,還是單數?
這沒有統一的規定。假如現在有兩種場景,擷取文章id為110的資料。那麼我可以這樣設計:
- GET /article/110 可以了解為擷取文章,id為110的資料
-
GET /articles/110 可以了解為從資料集中(文章集合)中擷取,id為110的資料
其實這兩種都是可以了解的。但是後者更能展現出從資料集中讀取資料,跟讀取資源的過程更貼切,例如:
SELECT * FROM articles WHERE id = 110;
是以為了統一起見,建議都使用複數 URL。
在響應正文中傳回錯誤詳細資訊
當API伺服器處理錯誤時,友善(并建議!)在JSON正文中傳回錯誤詳細資訊,以幫助使用者進行調試。
{
"error": "Invalid payoad.",
"detail": {
"surname": "This field is required."
}
}
發生錯誤時,不要傳回 200 狀态碼
就比如說,HTTP 相應的狀态碼是200,但是伺服器的響應可以是sucess也可能是error:
HTTP/1.1 200 OK
Content-Type: text/html
{
"status": "failure",
"data": {
"error": "Expected at least two items in list."
}
}
*結果,在判斷status狀态之前,我必須檢查狀态碼和臨時字段,以確定一切正常。這種設計是真正的禁忌,因為它破壞了API及其使用者之間的信任。
是以我們應該怎麼做呢?
使用狀态代碼,僅使用響應正文提供錯誤詳細資訊。
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": "Expected at least two items in list."
}
狀态碼
2xx 狀态碼
200狀态碼表示操作成功,但是不同的方法可以傳回更精确的狀态碼。
- GET: 200 OK
- POST: 201 Created
- PUT: 200 OK
- PATCH: 200 OK
-
DELETE: 204 No Content
上面代碼中,POST傳回201狀态碼,表示生成了新的資源;DELETE傳回204狀态碼,表示資源已經不存在。
此外,202 Accepted狀态碼表示伺服器已經收到請求,但還未進行處理,會在未來再處理,通常用于異步操作。
3xx 狀态碼
API 用不到301狀态碼(永久重定向)和302狀态碼(暫時重定向,307也是這個含義),因為它們可以由應用級别傳回,浏覽器會直接跳轉,API 級别可以不考慮這兩種情況。
API 用到的3xx狀态碼,主要是303 See Other,表示參考另一個 URL。它與302和307的含義一樣,也是"暫時重定向",差別在于302和307用于GET請求,而303用于POST、PUT和DELETE請求。收到303以後,浏覽器不會自動跳轉,而會讓使用者自己決定下一步怎麼辦。下面是一個例子。
HTTP/1.1 303 See Other
Location: /articles/110
4xx 狀态碼
4xx狀态碼表示用戶端錯誤,主要有下面幾種。
- 400 Bad Request:伺服器不了解用戶端的請求,未做任何處理。
- 401 Unauthorized:使用者未提供身份驗證憑據,或者沒有通過身份驗證。
- 403 Forbidden:使用者通過了身份驗證,但是不具有通路資源所需的權限。
- 404 Not Found:所請求的資源不存在,或不可用。
- 405 Method Not Allowed:使用者已經通過身份驗證,但是所用的 HTTP 方法不在他的權限之内。
- 410 Gone:所請求的資源已從這個位址轉移,不再可用。
- 415 Unsupported Media Type:用戶端要求的傳回格式不支援。比如,API 隻能傳回 JSON 格式,但是用戶端要求傳回 XML 格式。
- 422 Unprocessable Entity :用戶端上傳的附件無法處理,導緻請求失敗。
- 429 Too Many Requests:用戶端的請求次數超過限額。
5xx 狀态碼
5xx狀态碼表示服務端錯誤。一般來說,API 不會向使用者透露伺服器的詳細資訊,是以隻要兩個狀态碼就夠了。
- 500 Internal Server Error:用戶端請求有效,伺服器處理時發生了意外。
- 503 Service Unavailable:伺服器無法處理請求,一般用于網站維護狀态。
提供連結
這一種目前比較少用。但是可以考慮用。其實就是在擷取資源的時候,直接傳回下一步需要操作的URL。例如:
HTTP/1.1 200 OK
Content-Type: application/json
{
"status": "In progress",
"links": {[
{ "rel":"cancel", "method": "delete", "href":"/articles/status/110" } ,
{ "rel":"edit", "method": "put", "href":"/articles/status/12345" }
]}
}
參考連接配接
RESTful API Design: 13 Best Practices to Make Your Users Happy, by Florimond Manca
https://docs.microsoft.com/en-us/azure/architecture/best-practices/api-design