RESTful API定義及使用規範

fxm547發表於2018-01-22

首發於fxm5547的部落格

RESTful本身是一種風格而不是規範,本文為該風格的規範實現的最佳實踐,本文件詳細說明了HTTP RESTful API的定義和使用規範,作為介面呼叫者和實現者的重要參考。

介面風格

遵循RESTful設計風格,同時控制複雜度及易於使用,僅遵循大部分原則。 遵循原則:

  • 使用https協議
  • 版本號放入URL或Header
  • 只提供json返回格式
  • post,put上使用json作為輸入
  • 使用http狀態碼作為錯誤提示
  • Path(路徑)儘量使用名詞,不使用動詞,把每個URL看成一個資源
  • 使用HTTP動詞(GET,POST,PUT,DELETE)作為action操作URL資源
  • 過濾資訊
    • limit:指定返回記錄數量
    • offset:記錄開始位置
    • direction:請求資料的方向,取值prev-上一頁資料;next-下一頁資料
    • page:第幾頁
    • per_page:每頁條數
    • total_count:總記錄數
    • total_pages:總頁數,等於page時,表示當前是最後一頁
    • sort:column1,column2排序欄位
    • orderby:排序規則,desc或asc
    • q:搜尋關鍵字(uri encode之後的)
  • 返回結果
    • GET:返回資源物件
    • POST:返回新生成的資源物件
    • PUT:返回完整的資源物件
    • DELETE:返回一個空文件
  • 速率限制
    • X-RateLimit-Limit: 每個IP每個時間視窗最大請求數
    • X-RateLimit-Remaining: 當前時間視窗剩餘請求數
    • X-RateLimit-Reset: 下次更新時間視窗的時間(UNIX時間戳),達到下個時間視窗時,Remaining恢復為Limit

未遵循原則:

  • Hypermedia API(HATEOAS),通過介面URL獲取介面地址及幫助文件地址資訊
  • 限制返回值的域,fields=id,subject,customer_name
  • 快取,使用ETag和Last-Modified

參考:

模組和版本說明

介面模組相互對立且有版本管理,模組名作為APP配置項進行儲存,每個模組的版本號version和endpoint在應用初始化時呼叫api模組資訊介面(通過傳遞客戶端應用名稱和版本號獲取各個API模組的endpoint和version)獲取並儲存

  • 示例模組及最新版本號:
模組 模組用途 最新版本號
account 帳戶 v1
sms 簡訊 v1
open 一些開放介面,不需要公共引數 v1

公共引數

Headers

公共請求引數是指每個介面都可能需要傳遞的引數,公共引數通過header傳遞。

引數 是否必須 說明及header格式
app 所有介面必須 請求客戶端應用標識,取值*-ios、*-android、*-pc、*-h5
header格式:
X-Co-App: $app
user_id App登入後所有介面都傳
Web通過session機制獲取
使用者標識
header格式:
Authorization: CoAPI base64(user_id:token)
token App登入後所有介面都傳
Web通過session機制獲取
授權訪問令牌
header格式:
Authorization: CoAPI base64(user_id:token)
  • Web應用通過cookies傳遞session id,user_id和token無需傳遞,介面會從session自動獲取;

  • 同一token值在App和Web各應用間通用(token即為session id);

  • **APP修改user-agent,在原有user-agent的尾部新增$app/$versionNetType/$value。**如:

    • Dalvik/2.1.0 (Linux; U; Android 6.0.1; MI 4LTE MIUI/V7.5.3.0.MXGCNDE) $app-android/3.0.0 NetType/4G
    • Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_2 like Mac OS X) AppleWebKit/603.2.4 (KHTML, like Gecko) $app-ios/3.0.0 NetType/WIFI
  • app取值及釋義示例

app取值 客戶端名稱【域名】
admin-pc 管理中心PC網頁版【admin.url.com】
admin-h5 管理中心手機網頁版【admin.url.com】
admin-ios 管理中心iOS版
admin-android 管理中心Android版

Cookies

  • **用於告知服務端是否支援Webp的Cookie:**cookie name是supportWebp,取值是1(支援)和0(不支援),未傳遞時服務端預設取值為0。
  • Webview植入Session的Cookie:

JWT & OAuth2

  • Json Web Token可用於替代session-cookie機制。但會存在一些問題,比如為過期token強制失效問題(使用者修改了密碼後,無法強制其他的終端token全部失效)。
  • OAuth2是授權其他開發者訪問自己應用有限許可權的授權機制。

許可權

  • 許可權分為
    • none:無需任何授權;
    • token:需要使用者登入授權,可通過header AuthorizationCookie CoSID傳遞;
    • admintoken:需要管理員登入授權,可通過header AuthorizationCookie CoCPSID傳遞;
    • token || admintoken:使用者登入授權或管理員登入授權都可以;
      圖片
    • sign:需要簽名,一般用於服務端內部相互呼叫,詳見[ API HMAC-SHA1簽名]({% post_url 2017-11-08-API-HMAC-SHA1-Sign %})。

狀態碼說明

正確
介面正常訪問情況下,伺服器返回2××的HTTP狀態碼。

HTTP狀態碼
200 OK - 表示已在響應中發出、資源更改成功(GET、PUT)
201 Created - 新資源被建立(POST)
204 No Content - 資源被刪除(DELETE)

錯誤
當使用者訪問介面出錯時,伺服器會返回給一個合適的4××或者5××的HTTP狀態碼;以及一個application/json格式的訊息體,訊息體中包含錯誤碼code和錯誤說明message。

  • 5××錯誤(500=<status code)為伺服器或程式出錯,客戶端只需要提示“服務異常,請稍後重試”即可,該類錯誤不在每個介面中列出。
  • 4××錯誤(400=<status code<500)為客戶端的請求錯誤,需要根據具體的code做相應的提示和邏輯處理,message僅供開發時參考,不建議作為使用者提示。
  • 部分錯誤示例:
code message HTTP狀態碼
InvalidToken 未登入或授權過期,請登入 401 Unauthorized
ValidationError 輸入欄位驗證出錯,缺少欄位或欄位格式有誤 422 Unprocessable Entity
AccountNotExist 賬戶名不存在 404 Not Found
InvalidPassword 密碼錯誤 401 Unauthorized
NotFound 請求的資源不存在 404 Not Found
AccountHasExist 賬戶名已經存在 409 Conflict
MobileHasBinded 手機號已經繫結其他賬戶 409 Conflict
InvalidSign 引數簽名驗證未通過 403 Forbidden
InvalidSMSCode 簡訊驗證碼錯誤 403 Forbidden
ExpiredSMSCode 過期的簡訊驗證碼 403 Forbidden
FrequencyLimit 傳送過於頻繁,請稍後再試 403 Forbidden
TimesExceeded 達到最大傳送次數限制,請明天再試 403 Forbidden
VerifyTimesExceeded 達到最大校驗次數,請明天再試 403 Forbidden
RateLimitExceeded 介面呼叫次數超過限制,請稍後再試 429 Too Many Requests
|    |
複製程式碼

InternalError |服務異常,請稍後再試 |500 Internal Server Error

引數傳遞

遵循RESTful規範,使用了GET, POST, PUT, DELETE共4種請求方法。

  1. GET:請求資源,返回資源物件
  2. POST:新建資源,返回新生成的資源物件
  3. PUT:新建/更新資源,返回完整的資源物件
  4. DELETE:刪除資源,返回body為空
  • GET請求不允許有body, 所有引數通過拼接在URL之後傳遞,所有的請求引數都要進行遵循RFC 3986的URL Encode
  • DELETE刪除單個資源時,資源標識通過path傳遞,批量刪除時,通過在body中傳遞JSON。
  • POST, PUT請求,所有引數通過JSON傳遞,可選的請求引數,只傳有值的,無值的不要傳遞,contentType為application/json。

4種請求動作中,GET、PUT、DELETE是冪等的;只有POST是非冪等的。冪等操作的特點是其任意多次執行所產生的影響均與一次執行的影響相同。 是非冪等是判斷介面使用POST還是PUT的決定條件

注意: APP端獲取json資料時,對於數值型別欄位必須以數值型別轉換,無論傳遞過來的值是否帶引號。

圖片
圖片

速率限制Rate Limiting

  • 為了防止API被惡意呼叫,對API呼叫進行速率限制。
  • 速率限制為每IP每15分鐘5000次(dev/qa為10W)呼叫(15分鐘是一個時間視窗)。
  • 限制是針對所有介面模組一起計算的(Redis key為APIRL:{IP}),暫時沒有特殊的模組或單個介面(未來可能有)。
  • 你可以通過每個介面返回的HTTP headers瞭解當前速率限制的情況:
    • X-RateLimit-Limit: 每個IP每個時間視窗最大請求數
    • X-RateLimit-Remaining: 當前時間視窗剩餘請求數
    • X-RateLimit-Reset: 下次更新時間視窗的時間(UNIX時間戳),達到下個時間視窗時,Remaining恢復為Limit
  • 超出速率限制,返回以下錯誤
    圖片

安全注意事項

  • 使用者登入後使用者的token;aliyun OSS的bucket、AccessKey ID與AccessKey secret;微視訊的appid、sign、bucket;這些關鍵資料通過呼叫介面獲得,需要在客戶端以安全的方式儲存。
  • 音訊視訊在APP內的儲存,不允許被拷貝(即使越獄或root後拿走也無法使用)。

測試工具

推薦Chrome瀏覽器外掛Postman作為介面測試工具, Postman下載地址

圖片

文件生成工具

  • 生成的工具為apidoc,詳細閱讀官方文件:http://apidocjs.com

呼叫示例

  • 虛擬碼

    圖片

  • PHP

    圖片

API模組資訊獲取

  • App配置檔案中僅儲存api模組名,App初始化時請求獲取api模組資訊,獲取各個api模組的資訊(endpoint和version)。

介面文件參考示例

介面文件參考示例

相關文章