關於API設計
最近工作寫API的需求越來越頻繁,如何設計API的風格,是需要花心思和一些時間
就特定寫了一篇關於API設計原則
1.HTTPS
雖然這個沒太大關係、但是如果你開發的API是公開的,容易遭受到攻擊,影響到網站的狀況
2.API URL and Version
如果API的變化很大,可以搭配API設計成url名稱
ex:https://api.github.com/v1
ex:https://sample.com/api/v1
3.schema
返回的格式:建議用JSON,如果要用其他格式在head Accept指定,服務端需要返回正確status code
給詳細說明來
4.從資源中心的URL設計
在資源來說Restful API的核心概念,所有的操作都是以資源進行,資源就是URL表示,所以要簡潔,
明朗的URL設計,極度重要,可以從一些api部分來說明
/users/:username/repos
/users/:org/repos
/repos/:owner/:repo
/repos/:owner/:repo/tags
/repos/:owner/:repo/branches/:branch
注意:只能有名詞,不能用動詞,URL大小寫敏感,盡可能用小寫字母
.集合盡可能用復數來表示資源,單個資源可以用id來表示
.一個資源有很多URL
5.使用正確的Method
名稱 | 描述 |
HEAD | 取得HEAD資訊,例如取資源修改日期 |
GET | 取得資料 |
POST | 新增資料 |
PATCH | 局部更新(也可以新增) |
PUT | 完整更新(覆蓋過去) |
DELETE | 刪除 |
範例
- GET ~url/mermers 或 ~url/members/1
- POST ~url/members
- PUT ~url/members/1 (需指定id)
- PATCH ~url/members/1 (需指定id)
- DELETE ~url/members/1 (需指定id)
若遇到不符CRUD的狀況
- 使用POST,重新寄送POST/resend,為需要動作增加一個使用POST執行動作
- 增加控制參數,增加動作相關參數,透過修改參數來控制動作,EX:blog 文章發布,可用上面
POST /articles/{id}/pulish 或在文章部分加入published:boolean時候,發布就是更新
PUT /articles/{id}/?published=true - 動作轉換資源,增加一個/gists/:id/star子資源,然後對其進行操作:"喜歡"使用PUT/gists/:id/star,
取消喜歡使用DELETE /gists/:id/forks可以執行用戶fork action
6.讓Query更自由
Query透過參數的方式,來控制返回不同的結果
7.分頁Pagination
返回某個資源的列表時候,如果返回資料特別多時候EX:url/orders,需要分頁批次回傳資料結果,
分頁技術會用到上面提到url query,可以透過兩個參數返回結果
- per_page:每頁返回多少資料,沒提供會使用預設的值這個數字也有最大值
- page:要獲取每一頁資源,預設第一頁
返回資院列表為[(page-1)*per_page, page*per_page)
8.定義合適狀態碼
HTTP的status code:說明請求大致狀況,定義了完成、處理、錯誤,對於給予客戶端很重要,
狀態碼是三位的整數,下面是比較常見的狀況
2XX
:正常處理返回狀態碼3XX
:重定向,請求資源發生變化4XX
:Clinet 發送請求有誤5XX
:服務端異常錯誤
狀態碼 | LABEL | 解釋 |
---|---|---|
200 | OK | 請求成功接收並處理,一般回應中都會有body |
201 | Created | 請求已完成,並導致了一個或者多個資源被建立,最常用在POST 建立資源的時候 |
202 | Accepted | 請求已經接收並開始處理,但是處理還沒有完成。一般用在異步處 理的情況,回應body 中應該告訴客戶端去哪裡查看動作的狀態 |
204 | No Content | 請求已經處理完成,但是沒有訊息要返回,經常用在PUT 更新資源 的時候(客戶端提供資源的所有屬性,因此不需要服務端返回)。 如果有重要的metadata,可以放到頭部返回 |
301 | Moved Permanently | 請求的資源已經永久性地移動到另外一個地方,後續所有的請求 都應該直接訪問新地址。 服務端會把新地址寫在 Location 頭部字段,方便客戶端使用。允許客戶端把POST請求修改為GET。 |
304 | Not Modified | 請求的資源和之前的版本一樣,沒有發生改變。用來緩存資源, 和條件性請求(conditional request)一起出現 |
307 | Temporary Redirect | 目標資源暫時性地移動到新的地址,客戶端需要去新地址進行操 作,但是不能修改請求的方法。 |
308 | Permanent Redirect | 和301類似,除了客戶端不能修改原請求的方法 |
400 | Bad Request | 客戶端發送的請求有錯誤(請求語法錯誤,body 資料格式有誤, body 缺少必須的字段等),導致服務端無法處理 |
401 | Unauthorized | 請求的資源需要認證,客戶端沒有提供認證訊息或者認證訊息不 正確 |
403 | Forbidden | 服務器端接收到並理解客戶端的請求,但是客戶端的權限不足。 EX:普通用戶想操作只有管理員才有權限的資源。 |
404 | Not Found | 客戶端要訪問的資源不存在,鏈接失效或者客戶端偽造URL 的 時候回遇到這個情況 |
405 | Method Not Allowed | 服務端接收到了請求,而且要訪問的資源也存在,但是不支持 對應的方法。服務端必須返回 Allow 頭部,告訴客戶端哪些方法是允許的 |
415 | Unsupported Media Type | 服務端不支持客戶端請求的資源格式,一般是因為客戶端在Content-Type 或者Content-Encoding 中申明了希望的返回格式,但是服務端沒有實現。比如,客戶端希望收到 xml 返回,但是服務端支持Json |
429 | Too Many Requests | 客戶端在規定的時間裡發送了太多請求,在進行限流的時候會 用到 |
500 | Internal Server Error | 服務器內部錯誤,導致無法完成請求的內容 |
503 | Service Unavailable | 服務器因為負載過高或者維護,暫時無法提供服務。服務器端 應該返回 Retry-After 頭部,告訴客戶端過一段時間再來重試 |
詳細參考:https://httpstatuses.com/
9.錯誤處理:給詳細訊息
如果出錯的時候,給予response body通過,message詳細訊息。
一般返回代碼,一般返回4xx Bad request結果,結果很模糊,如果給予
message的話,可知道哪裡有問題,迅速修改。
- 如果Json無法解析,返回Problems parsing Json
- 缺少必要欄位則,返回402 Unprocessable Entity,除了message
通過errors 給予哪一個field缺乏,方便調用快速排錯
10.驗證和授權
- 驗證:確認用戶身分
- 授權:針對特定資源有操作權限
若沒通過驗證,返回401 Unauthorized 具體錯誤,若沒有授權則返回403 Forbidden,提供詳細錯誤訊息
11.rate limit
訪問次數不加控制,會造成API濫用,也容易DDOS,依據使用者身分來限流,可防止伺服器壓力。
X-RateLimit-Limit
: 用戶每小時予許請求最大值X-RateLimit-Remaining
:當下時間剩下可用的請求數量X-RateLimit-Rest
: 時間重整狀況,到這時間點請求X-RateLimit-Limit
的值
對於超過流量的請求,可以返回429 Too many requests狀態碼,並附帶錯誤訊息。
12.Hypermedia API
RestfulAPI設計最好做到Hypermedia,返回結果中提供相關資源連結,例如api.github.com
13.寫出良好的API文件
API是給人用的,不管公司內部或是公開API都是一樣,遵循規範,若別人不知道怎麼使用開發的API
對每個請求和返回參數給予說明,給一個完整範例,最終目標是能夠依據文件,可以使用你的API或開發
API
參考URL:https://www.footmark.info/programming-language/design/restful-webapi-design-guide/
元哥的筆記