Rest API Design

本人最近負責Zuora Rest API的設計工作,總結了一下Restful設計的規範。


1. 給API加上版本

API版本應該是必備的。這樣API不會隨時間過時。一種方法是把版本放到URL裏(/api/v1...)


另一個巧妙的花招是使用 Accept HTTP header,來傳遞需要的版本,正如github所做的。(https://developer.github.com/v3/media/#request-specific-version)


(備註:Github 的格式是,application/vnd.github[.version].param[+json],version指定版本,param是想要的格式,txt,html等。從評論看似乎Github的方式更完美)


通過版本,你可以改變API的結構,而不用擔心老版客戶端的兼容問題。(備註:API提供者默默承受維護多套API的痛苦)


2. 使用名詞,而不是動詞

我經常看到有人使用動詞而不是名詞來表示資源名稱,例如下面這些:

* /getProducts

* /listOrders

* /retreiveClientByOrder?orderId=1


從結構整潔和一致角度考慮,你應該總是使用名詞。而且,巧妙使用 HTTP 方法(GET,POST)可以把想要的操作從資源名稱上去除。如下面的例子:

* GET /products 返回所有產品列表

* POST /products 添加產品到產品列表

* GET /products/4 提取Id爲4的產品

* PATCH/PUT /products/4 更新Id爲4的產品


3. 使用複數形式

在我看來,同一資源命名,混合使用單數和複數形式不是好主意。很快就會混淆,帶來不一致。


即使對 show/delete/update 操作,使用 /artists 而不是 /artist 也更好點。


4. GET 和 HEAD 操作應該是安全的(無副作用)

RFC2616 明確規定 HEAD 和 GET 必須是安全的(不能改變資源狀態)


右邊是一個不好的例子: GET /deleteProduct?id=1


如果搜索引擎檢索了那個頁面,畫面太美我不敢看(備註:實踐中對刪除操作都有權限驗證,就算操作引擎抓取也沒啥破壞)


(備註:POST和PUT的區別,POST是不冪等的,PUT是冪等的。如果多次調用URL得到的結果都一樣,那就是冪等的。例如,發評論,如果評論ID在提交評論前已經生成,那麼無論點多少次提交,看到的都是一條評論。如果評論ID在提交評論後生成,點多少次提交就看到多少條評論。)


5. 使用嵌套資源

如果想獲取全部的子集,使用嵌套路由來讓風格簡潔。例如想從所有唱片中選取特定的,使用 GET /artists/8/albums (備註:這裏8就是所謂嵌套路由,指導選取哪個唱片)


6. 分頁

通過 HTTP 返回超大結果集不是好主意。序列化大的JSON數據很慢,這會導致性能問題。


通常的做法是分頁,Facebook,Twitter,Github都是這麼做的。提取少裏數據更快,就算需要多次調用,也比一次提取很大(但執行很慢)的數據更高效。


如果想分頁,一個好的方法是通過LINK HTTP header,來提示前一頁和後一頁。正如 Github 做的那樣。


(備註:LINK的用法 Link: <http://next_url>; rel="next", <http://last_url>; rel="last", <http://first_url>; rel="first", <http://prev_url>; rel="prev")


7. 使用合適的 HTTP 狀態碼

請求返回時,無論請求成功與否,總是使用正確的返回碼。下面是一些可能用到的狀態碼。

7.1 成功狀態碼(2XX系列)

* 201 Created 當成功創建資源時(INSERT)

* 202 Accepted 當請求被接受,並放到後臺執行時(異步任務)

* 204 No Content 當請求成功,但是沒有內容返回時(例如 DELETE 時)

(備註:是否 200 就足夠了,引入其它是否增加理解負擔)


7.2 客戶端錯誤(4xx系列)

* 400 Bad Request 當處理querystring或http body時出錯(例如非法JSON)

* 401 Unauthorized 認證失敗

* 403 Forbidden 認證成功時,操作或請求的資源不被允許

* 406 Not Acceptable 請求格式不被接受(例如試圖請求JSON數據,但服務器只提供XML)

* 410 Gone 請求的資源被永久刪除(備註:咋判斷是不存在還是被永久刪除了)

* 422 Unprocessable entity 當創建對象時發生可用性錯誤


8. 總是返回一致的錯誤內容

當發生錯誤時,總是返回一致的錯誤描述。錯誤結構總是相同,這樣更容易解析錯誤信息。


如下描述,清晰,簡單,自說明

HTTP/1.1 401 Unauthorized

{

"status": "Unauthorized",

"message": "No access token provided.",

"request_id": "594600f4-7eec-47ca-8012-02e7b89859ce"

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章