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/$version
和NetType/$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 Authorization
和Cookie CoSID
傳遞; -
admintoken
:需要管理員登錄授權,可通過header Authorization
和Cookie 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 |
-
HTTP狀態碼參考
圖片
參數傳遞
遵循RESTful規范,使用了GET, POST, PUT, DELETE共4種請求方法。
- GET:請求資源,返回資源對象
- POST:新建資源,返回新生成的資源對象
- PUT:新建/更新資源,返回完整的資源對象
- 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)。