RESTful接口規範

什麼是RESTful

REST(Representational State Transfer)是一種輕量級的Web Service架構風格,能夠翻譯成「表述性狀態轉移」,實現和操做明顯比SOAP和XML-RPC更爲簡潔,能夠徹底經過HTTP協議實現,還能夠利用緩存Cache來提升響應速度,性能、效率和易用性上都優於SOAP協議.html

通俗來說就是:資源在網絡中以某種表現形式進行狀態轉移,RESTful即這種設計的風格前端

用一句話概述即:URL定位資源,用HTTP動詞描述操做算法

REST架構遵循了CRUD原則,CRUD原則對於資源只須要四種行爲就能夠完成對其操做和處理:數據庫

  • GET (SELECT): 從服務器取出資源(一項或多項)
  • POST (CREATE): 在服務器新建一個資源
  • PUT (UPDATE): 在服務器更新完整的資源(客戶端提供改變後的完整資源)
  • PATCH (UPDATE):在服務器更新資源(客戶端提供改變的屬性)
  • DELETE (CREATE): 從服務器刪除資源

REST把HTTP對一個URL資源的操做限制在GET、POST、PUT和DELETE這四個以內。這種針對網絡應用的設計和開發方式,能夠下降開發的複雜性,提升系統的可伸縮性.json

更多REST API背景知識能夠參考這篇 RESTful API 設計指南api

分URI規範,Action操做規範,參數規範,狀態碼規範數組

設計流程

  1. 肯定一個API提供什麼類型的資源
  2. 肯定資源之間的依賴關係
  3. 基於類型和依賴關係肯定資源的命名
  4. 肯定資源的結構
  5. 爲資源添加最少的方法

【強制】瀏覽器

【推薦】緩存

【參考】安全

說明:

正例:

反例:

URI 規範

1.【強制】已肯定/發佈的接口禁止修改請求方法/URI/參數名/返回值結構/內容,禁止刪除接口/參數/返回值中的屬性。

說明:

若有上述變動,請新啓用一個接口
容許新增參數,但該參數不能爲必填,如必填需提供缺省值兼容舊的調用

2.【強制】URI 中只容許用小寫字母,不用大寫。
正例:

https://example.com/api/gaoshou/v1/users
https://example.com/api/gaoshou/v1/mails:

反例:

https://example.com/api/GaoShou/V1/Users
https://example.com/api/gaoshou/V1/Mails

3.【強制】URI 中用中槓 - 分割單詞不用下劃槓 _

正例:

https://example.com/api/gaoshou/v1/user-mails

反例:

https://example.com/api/gaoshou/v1/user_mails

4.【強制】URI 不能以"/"結尾。

正例:

/gaoshou/v1/users

反例:

/gaoshou/v1/users/

5.【強制】URI 中不能包含空格。

6.【強制】URI 不能以文件後綴結尾。

7.【推薦】將 API 的版本號放入 URI 中, 因爲一個項目多個 APP 或微服務因此使用如下風格, 將版本號放到 APP 後面

https://example.com/api/:app:/:version:/:resource:

正例:

https://example.com/api/gaoshou/v1/users
https://example.com/api/assets/v1/assets/1

8.【強制】每一個 URI 表明一種資源,因此不能有動詞,只能有名詞(特殊狀況可使用動詞),並且所用的名詞每每與數據庫的表格名對應,名詞必須是清晰簡潔的英文單詞,不容許用拼音替代。

正例:

/gaoshou/v1/users

反例:

/gaoshou/v1/get-users

9.【推薦】通常來講, 數據庫中的表都是同種記錄的"集合"(Collection), 因此 API 中的名詞也應該使用複數(若是沒有複數形式,應使用單數)。舉例來講數據庫中的 Users 列表, Courses 列表。

正例:

/gaoshou/v1/users
/assets/v1/assets/1

10.【推薦】避免使用籠統的表示,例如objects、values、types

11.【推薦】URI 中的可變部分, 通常用來傳遞該 API 操做的核心實體對象的惟一ID。若是沒有惟一ID的單一對象則以單數單詞做爲對象ID。

正例:

/assets/1 [GET, PUT, DELETE]
/materials/wood [GET, PUT, DELETE]

12.【強制】URI 中指定5個之內資源對象的操做id能夠在URI路徑上用逗號,分割。更多則以batch結尾,相關參數在請求體中。

正例:

/assets/1,2,3 [GET, PUT, DELETE] //id爲1,2,3的資源
/assets/batch [POST, PUT]

13.【參考】避免層級過深的 URI。在 URI 中表達層級,用於按實體關聯關係進行對象導航,通常根據id導航。
過深的導航容易致使 URI 膨脹,不易維護,儘可能使用查詢參數代替路徑中的實體導航。建議不超過3個層級。

正例:

/assets/1?area=2&act=3

反例:

/assets/1/area/2/act/3

14.【推薦】若是有除id外更多的參數須要提供, GET 方法請使用 URL Parameter(例如:"?clientId=xxxxx&appId=xxxxxx"), PUT/POST/DELETE 方法請使用請求體傳遞參數。

15.【強制】URI 傳遞參數列表要ENCODE,特別是UNICODE字符必定要ENCODE。

16.【強制】URI 映射應避免 /{xx}/{xx} 的使用。

說明:

相似該路徑,效率低,並且不容易理解路徑
例如:/{uid}/{lable}
建議修改成/user/{uid}/lable/{lableId}
修改後直接能夠根據路徑理解該API意義(ID爲lableId的用戶的標籤)

Action操做規範

1.【強制】經過標準HTTP方法對資源CRUD。

說明:

  • GET (SELECT): 從服務器取出資源(一項或多項)
  • POST (CREATE): 在服務器新建一個資源
  • PUT (UPDATE): 在服務器更新完整的資源(客戶端提供改變後的完整資源)
  • PATCH (UPDATE):在服務器更新資源(客戶端提供改變的屬性)
  • DELETE (CREATE): 從服務器刪除資源

2.【參考】正常狀況下全部R(獲取數據)操做都使用 GET 方法,查詢內容參數使用QueryParams(僅容許在查詢請求參數很是多的狀況下,如參數數量大於10個,纔可使用POST)。

3.【強制】GET 查詢從服務器取資源一項必須提供資源id,多項必須是資源集合的 URI,即複數結尾。

正例:

/assets/1
/assets

4.【強制】狀況須要R(獲取數據)操做使用POST 方法的 URI 必須以 query (一項)或 list (多項)結尾。

正例:

/assets/query [POST]
/assets/list [POST]

5.【推薦】獲取單個對象應該返回整個對象,獲取多個對象應該返回一些可選項屬性。

6.【強制】全部C(建立資源)操做都使用 POST 方法。C操做通常向」資源集合「型URI發起。必須傳遞一個資源對象(不是屬性),這樣即便對象的結構發生變化,也不須要去更新方法或者對象結構,那些棄用的字段則須要標識爲「只讀」。

正例:

/assets [POST]   // 新增資源
/zoos/1/employees [POST] //爲id爲1的動物園僱傭員工

7.【強制】若是隻支持一個完整對象的更新,U(更新資源)操做必須使用 PUT 方法。

正例:

/animals/1 [PUT] // 更新id爲1的動物

8.【推薦】若是隻更新一個對象的部分屬性,U(更新資源)操做使用 PATCH 方法。

9.【強制】全部D(刪除資源)操做都使用 DELETE 方法。

正例:

/zoos/1/employees/2 [DELETE] // 刪除id爲1的動物園內id爲2的僱員
/zoos/1/employees/2,4,5 [DELETE] // 刪除id爲1的動物園內id爲2,4,5的僱員
/zoos/1/animals  // 刪除id爲1的動物園內的全部動物

10.【強制】DELETE 方法沒有請求體,接口上必須不能包含RequestBody。

11.【推薦】若是是當即刪除,應該返回空;若是是啓動一個刪除操做,應該返回一個刪除操做;若是隻是標識某個資源是「被刪除的」,應該返回一個更新後的資源;若是多個刪除請求刪除同一資源,那麼只有第一個請求才應該成功,其餘的返回404(not found)。

12.【參考】各Action操做須要保證操做的安全性和冪等性。

說明:

  • 安全性 :不會改變資源狀態,能夠理解爲只讀的;
  • 冪等性 :執行1次和執行N次,對資源狀態改變的效果是等價的。
Action 安全性 冪等性
READ
CREATE
UPDATE
DELETE

安全性和冪等性均不保證反覆請求能拿到相同的響應。以 DELETE 爲例,第一次 DELETE 返回 200 表示刪除成功,第二次返回 404 提示資源不存在,這是容許的。

13.【強制】自定義操做方法應該用於基本方法不能實現的功能性方法。可能須要一個任意請求並返回一個任意的響應,也多是流媒體請求和響應。

14.【強制】自定義方法應該使用 POST/PUT/PATCH 方法。

15.【強制】自定義方法批量(超5個id)應該遵循如下規範。

| 自定義方法 | 方法 | URI 結尾 | 請求體 | 響應 |
|---|---|---|---|
| 批量多id查詢 | POST | list | JSON 資源id數組,如[1,2,3,4,5,6] | JSON 資源列表數組 |
| 批量添加 | POST | batch-create | JSON 資源列表數組 | JSON 資源id數組 |
| 批量刪除 | POST | batch-delete | JSON 資源id數組 | 空JSON對象, {} |
| 批量修改 | PUT | batch-update | JSON 資源列表數組 | 空JSON 資源列表數組 |
| 批量修改某屬性 | PATCH | batch-update | JSON 資源列表數組 | JSON 資源列表數組 |

16.【強制】自定義方法查詢集合數量的 URI 應該以 count 結尾,返回體爲JSON對象 {"count": ""}

17.【強制】自定義方法對資源執行某一動做(好比發送消息,啓用什麼功能),若是是針對資源的,則 URI 以動做爲動詞結尾,若是是針對資源屬性的,則 URI 以動做爲動詞結尾,屬性做爲參數。

正例:

描述 動做 HTTP Mapping 請求體 響應體
對資源執行某一動做 customVerb /custom-verb [POST]
取消某種操做 cancel /cancel [POST] N/A {"result": 0/1}
從回收站中恢復一個資源 undelete /projects/1/undelete [POST] N/A {"result": 0/1}
檢查項目是否重名 checkName /projects/1/check?name= [POST] N/A {"result": 0/1}

18.【推薦】比較複雜的接口不能肯定是使用 POST 仍是 PUT 時,要看具體的業務層代碼,看看接口產生的結果是否冪等,若是冪等用 PUT,相反用 POST。

參數規範

1.【強制】接口請求體和響應體接受參數格式均爲JSON("application/json")。請求頭爲 Content-Type:application/json;charset=UTF-8

2.【強制】Query和JSON中參數中用駝峯命名。

3.【推薦】默認將Date的輸入輸出轉爲Long型時間戳。

4.【強制】對象和方法命名語義需與內部保持一致,不容許自行創造。好比不要把Member叫作Person。

5.【強制】全部批量查詢接口均須要分頁。

6.【推薦】常見參數約定,查詢能夠捎帶如下參數。

描述 示例 備註
過濾條件 ?type=1&age=16 容許必定的 URI 冗餘,如 /projects/1 與 /projects?id=1
排序 ?sort=age&orde=asc 指定返回結果按照哪一個屬性排序,以及排序順序
投影 ?whiteList=id,name,email 指定返回字段
分頁 ?page=2&limit=100 指定第幾頁,以及每頁的記錄數
分頁 ?offset=10 指定返回記錄的開始位置,若是NoSql能夠是遊標
搜索 ?keyword=localhost 模糊搜索

7.【推薦】常用的、複雜的查詢能夠標籤化,這樣能夠下降維護成本。

正例:

/trades?status=closed&sort=created,desc [GET]

快捷方式:

/trades#recently-closed [GET]
或者
/trades/recently-closed [GET]

8.【強制】全部的接口都會上傳一部分基本信息,方便後臺認證和統計信息,這部分信息會在每一個接口的Head裏。
HEAD要求添加內容以下:

HEAD KEY Value 描述
t ${token} (可選)若是已經登陸的接口須要傳用戶的Token,未登陸接口不須要
a ${app} (必填)APPID,不一樣應用區分不一樣的應用id,用以數據隔離,不準私自定義,須要申請
v ${version} (必填)應用版本號,純數字格式,按照排期統一規劃,用以不一樣版本數據隔離
ev ${version} (可選)運行應用環境版本號,純數字格式,可用於Web頁面統計原生環境版本號,通常由客戶端經過url傳入
n ${versionName} (可選)應用版本名, 字符串
en ${versionName} (可選)運行應用環境版本名, 字符串,可用於Web頁面統計原生環境版本名,通常由客戶端經過url傳入
p ${platform} (必填)平臺,Android爲 1;IOS爲 2;Web爲 3
ep ${platform} (可選)運行應用環境平臺,Android爲 1;IOS爲 2,通常由客戶端經過url傳入
m ${model} (可選)設備描述信息,如MI 2,iPhone 4,Web頁面通常由客戶端經過url傳入
s ${sdk} (可選)系統SDK版本, Web頁面通常由客戶端經過url傳入
u ${uuid} (必填)設備惟一標識, Web頁面通常由客戶端經過url傳入
d ${time} (必填)時間戳, 請求接口當前時間戳。說明:每次請求都帶上當前時間的時間戳, 服務器收到請求後對比時間差,超過必定時長(如5分鐘),則認爲請求失效。時間戳超時機制是防護DOS攻擊的有效手段。
r ${random} (可選)隨機字符串, 每一個請求生成的隨機字符串。說明:每次請求都帶上客戶端隨機字符串, 服務器收到請求後對比是否請求過, 若是之前請求過, 則認爲請求失效。用以防止重放攻擊。
c ${md5-check} (可選)校驗信息。說明:不一樣的接口能夠選擇不一樣程度的校驗算法。請參考簽名算法爲時間戳+[token
h ${channel} (可選)渠道
o ${origin} (可選)來源,可用於標註通常第三方調用
i ${activity} (可選)活動,可用於標註活動
Referer ${Referer} (可選)請求接口來自的頁面
User-Agent ${User-Agent} (可選)瀏覽器信息

應用Id對應表

Code 應用
0 後臺專用
1 超級萬學
2 考研高手
3 創世界
4 超級萬學-創新創業
5 創新創業
12 神龍考研

9.【推薦】正常返回體應該包含HTTP請求狀態碼和服務器響應時間戳。結果以 result 爲關鍵字返回。

正例:

{
		"status": "返回成功狀態碼,成功即爲200",
		"timestamp": "響應時間戳",
		"result": "返回的數據"
	}
key type desc
status int 返回成功狀態碼,成功即爲200
timestamp long 響應時間戳
result Object 返回的數據

10.【強制】禁止採用前端 URI 傳遞的當前用戶Id,必須從Header中取Token,經過Token獲取當前用戶Id。

狀態碼規範

1.【強制】接口調用成功時返回HTTP狀態碼爲200,返回數據結果爲標準Json格式。如調用錯誤會返回除200以外的其餘HTTP狀態碼,返回數據結果也爲標準Json格式。

2.【推薦】隨着系統發展,總有一些API失效或者遷移,對失效的API,返回404 not found 或 410 gone;對遷移的API,返回 301重定向。

3.【推薦】服務器向用戶返回的狀態碼和提示信息, 常見的有如下一些。

HTTP CODE 含義 方法 描述
200 OK [GET] 服務器成功返回用戶請求的數據, 該操做是冪等的(Idempotent)。
201 Created,被建立 [POST/PUT/PATCH] 用戶新建或修改數據成功。
202 Accepted,被採納 [*] 表示一個請求已經進入後臺排隊(異步任務)。
204 No Content,被採納 [DELETE] 用戶刪除數據成功。
206 Partial Content,部份內容 [GET] 通常爲分片下載內容
301 Moved Permanently,永久移動 [GET] 請求的資源已被永久的移動到新URI,返回信息會包括新的URI,請求會自動定向到新URI。從此任何新的請求都應使用新的 URI 代替
302 Found,找到 [GET] 與301相似。但資源只是臨時被移動。客戶端應繼續使用原有 URI
304 Not Modified,未修改 [GET] 所請求的資源未修改,服務器返回此狀態碼時,不會返回任何資源。客戶端一般會緩存訪問過的資源,經過提供一個頭信息指出客戶端但願只返回在指定日期以後修改的資源
400 Bad Request,錯誤請求 [POST/PUT/PATCH] 用戶發出的請求有錯誤, 服務器沒有進行新建或修改數據的操做, 該操做是冪等的。經常使用於參數校驗。
401 Unauthorized,未受權 [*] 表示用戶沒有權限(令牌、用戶名、密碼錯誤)。常見於未登陸須要登陸,若是登陸後尚未權限應該返403。
403 Forbidden,拒絕請求 [*] 表示用戶獲得受權(與401錯誤相對), 可是訪問是被禁止的。
404 Not Found,未找到 [*] 用戶發出的請求針對的是不存在的記錄, 服務器沒有進行操做, 該操做是冪等的。
405 Method Not Allowed,方法不容許 [*] 請求中的方法未找到或被禁止。
406 Not Acceptable,不被採納 [GET] 用戶請求的格式不可得(好比用戶請求JSON格式, 可是隻有XML格式)。
409 Conflict,資源衝突 [PUT] 完成 PUT 請求時可能返回此代碼,服務器處理請求時發生了衝突。
410 Gone,資源已經不存在 [GET] 用戶請求的資源被永久刪除, 且不會再獲得的。410不一樣於404,若是資源之前有如今被永久刪除了可以使用410代碼。
422 Unprocesable entity,非法對象 [POST/PUT/PATCH] 當建立一個對象時, 發生一個驗證錯誤。
500 Internal Server Error,服務器內部錯誤 [*] 服務器發生錯誤, 用戶將沒法判斷髮出的請求是否成功。非業務異常,通常由框架拋出。
501 Not Implemented,未實現 [*] 服務器不支持請求的功能,沒法完成請求。
503 Service Unavailable,服務不可用 [*] 因爲超載(接口被限流)或系統維護,服務器暫時的沒法處理客戶端的請求。延時的長度可包含在服務器的Retry-After頭信息中。

4.【強制】不要發生了錯誤但給2xx響應,客戶端可能會緩存成功的 HTTP 請求。

5.【參考】正確設置 HTTP 狀態碼,不要自定義。

6.【參考】對非業務類異常,線上能夠統一文案如"服務器端錯誤,請稍後再試"。

響應規範

1.【強制】若是狀態碼是4xx, 就應該向用戶返回出錯信息。出錯信息格式以下。

{
  "status":400,	
  "error": "自定義錯誤碼",
  "msg": "錯誤描述",
  "timestamp": 123456,
  "exception": "報錯Exception類型",
  "show":1	
}
Key Type 描述
status Int (可選)同 HTTP 狀態碼,通常爲方便日誌統計
error String (必填)自定義錯誤碼,能夠經過錯誤碼定位到具體錯誤,通常全系統惟一
msg String (必填)錯誤具體描述
timestamp Long (可選)服務器時間戳
exception String (可選)報錯Exception類型, 如IOException,通常不面向前端
show Int (可選)0: 前端不需展現; 1: 前端可Toast展現; 2: 前端可對話框展現; 默認 0

2.【強制】若是狀態碼是2xx,服務器向用戶返回的結果應該將 reslut 做爲鍵名, 返回對象做爲鍵值。通常格式以下。

{
  "status": "返回狀態碼",
  "timestamp": "時間戳",
  "result": "返回的對象"
}
Key Type 描述
status Int (可選)同 HTTP 狀態碼,通常爲方便日誌統計
timestamp Long (可選)服務器時間戳
result Object 返回的對象

2.【強制】針對不一樣操做, 服務器向用戶返回的結果應該符合如下規範。

Key Type 描述
GET /assets 返回資源對象的列表(數組)
GET /assets/resource 返回單個資源對象
POST /assets 返回新生成的資源對象
PUT /assets/resource 返回完整的資源對象
PATCH /assets/resource 返回完整的資源對象
DELETE /assets/resource 返回一個空文檔

簽名算法

按照不一樣接口的功能,能夠把接口安全級別分爲明文模式、參數校驗模式、RSA簽名校驗模式。

明文模式

明文模式,的校驗信息生成規則爲: 時間戳+[random_str]+[token|uuid]+[url]+app鹽 取md5值。

協議中包含字段random_str,主要保證簽名不可預測。推薦生成隨機數算法以下:調用隨機數函數生成,將獲得的值轉換爲字符串。

[token|uuid]: 若是有token則傳token,若是沒有則傳設備uuid,若是都沒有則不傳。

[url]: 爲完整的接口連接。

參數校驗模式

參數校驗模式,是在明文模式基礎上對RequestBody的參數進行簽名,校驗信息生成規則爲: 時間戳+[random_str]+[token|uuid]+[url]+[請求RequestBody字典排序串]+app鹽 取md5值。

設全部發送或者接收到的數據爲集合M,將集合M內非空參數值的參數按照參數名ASCII碼從小到大排序(字典序),使用URL鍵值對的格式(即key1=value1&key2=value2…)拼接成字符串stringA。

特別注意如下重要規則:

  • 參數名ASCII碼從小到大排序(字典序);
  • 若是參數的值爲空不參與簽名;
  • 若是參數的值爲對象,則默認設置爲空對象{}
  • 參數名區分大小寫;
  • 接口可能增長字段,驗證簽名時必須支持增長的擴展字段;

RSA簽名校驗模式

RSA簽名校驗模式,是在參數校驗模式基礎上對生成的簽名信息RSA加密。此模式通常用於第三方服務器之間的高安全要求校驗。原則就是RSA密鑰保存是可靠安全的。

文章來源:劉俊濤的博客 歡迎關注公衆號、留言、評論,一塊兒學習。

如有幫助到您,歡迎點擊推薦,您的支持是對我堅持最好的確定(_)

相關文章
相關標籤/搜索