RESTful本身是一種風格而不是規(guī)范,本文為該風格的規(guī)范實現(xiàn)的最佳實踐,本文檔詳細說明了HTTP RESTful API的定義和使用規(guī)范,作為接口調(diào)用者和實現(xiàn)者的重要參考。
接口風格
遵循RESTful設(shè)計風格,同時控制復雜度及易于使用,僅遵循大部分原則。
遵循原則:
- 使用https協(xié)議
- 版本號放入URL或Header
- 只提供json返回格式
- post,put上使用json作為輸入
- 使用http狀態(tài)碼作為錯誤提示
- Path(路徑)盡量使用名詞,不使用動詞,把每個URL看成一個資源
- 使用HTTP動詞(GET,POST,PUT,DELETE)作為action操作URL資源
- 過濾信息
- limit:指定返回記錄數(shù)量
- offset:記錄開始位置
- direction:請求數(shù)據(jù)的方向,取值prev-上一頁數(shù)據(jù);next-下一頁數(shù)據(jù)
- page:第幾頁
- per_page:每頁條數(shù)
- total_count:總記錄數(shù)
- total_pages:總頁數(shù),等于page時,表示當前是最后一頁
- sort:column1,column2排序字段
- orderby:排序規(guī)則,desc或asc
- q:搜索關(guān)鍵字(uri encode之后的)
- 返回結(jié)果
- GET:返回資源對象
- POST:返回新生成的資源對象
- PUT:返回完整的資源對象
- DELETE:返回一個空文檔
- 速率限制
- X-RateLimit-Limit: 每個IP每個時間窗口最大請求數(shù)
- X-RateLimit-Remaining: 當前時間窗口剩余請求數(shù)
- X-RateLimit-Reset: 下次更新時間窗口的時間(UNIX時間戳),達到下個時間窗口時,Remaining恢復為Limit
未遵循原則:
- Hypermedia API(HATEOAS),通過接口URL獲取接口地址及幫助文檔地址信息
- 限制返回值的域,fields=id,subject,customer_name
- 緩存,使用ETag和Last-Modified
參考:
模塊和版本說明
接口模塊相互對立且有版本管理,模塊名作為APP配置項進行存儲,每個模塊的版本號version和endpoint在應(yīng)用初始化時調(diào)用api模塊信息接口(通過傳遞客戶端應(yīng)用名稱和版本號獲取各個API模塊的endpoint和version)獲取并存儲。
- 示例模塊及最新版本號:
| 模塊 | 模塊用途 | 最新版本號 |
|---|---|---|
| account | 帳戶 | v1 |
| sms | 短信 | v1 |
| open | 一些開放接口,不需要公共參數(shù) | v1 |
公共參數(shù)
Headers
公共請求參數(shù)是指每個接口都可能需要傳遞的參數(shù),公共參數(shù)通過header傳遞。
| 參數(shù) | 是否必須 | 說明及header格式 |
|---|---|---|
| app | 所有接口必須 | 請求客戶端應(yīng)用標識,取值*-ios、*-android、*-pc、*-h5header格式: X-Co-App: $app
|
| user_id |
App登錄后所有接口都傳, Web通過session機制獲取 |
用戶標識 header格式: Authorization: CoAPI base64(user_id:token)
|
| token |
App登錄后所有接口都傳, Web通過session機制獲取 |
授權(quán)訪問令牌 header格式: Authorization: CoAPI base64(user_id:token)
|
Web應(yīng)用通過cookies傳遞session id,user_id和token無需傳遞,接口會從session自動獲??;
同一token值在App和Web各應(yīng)用間通用(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/4GMozilla/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網(wǎng)頁版【admin.url.com】 |
| admin-h5 | 管理中心手機網(wǎng)頁版【admin.url.com】 |
| admin-ios | 管理中心iOS版 |
| admin-android | 管理中心Android版 |
Cookies
-
用于告知服務(wù)端是否支持Webp的Cookie:cookie name是
supportWebp,取值是1(支持)和0(不支持),未傳遞時服務(wù)端默認取值為0。 - Webview植入Session的Cookie:
JWT & OAuth2
- Json Web Token可用于替代session-cookie機制。但會存在一些問題,比如為過期token強制失效問題(用戶修改了密碼后,無法強制其他的終端token全部失效)。
- OAuth2是授權(quán)其他開發(fā)者訪問自己應(yīng)用有限權(quán)限的授權(quán)機制。
權(quán)限
- 權(quán)限分為
-
none:無需任何授權(quán); -
token:需要用戶登錄授權(quán),可通過header Authorization和Cookie CoSID傳遞; -
admintoken:需要管理員登錄授權(quán),可通過header Authorization和Cookie CoCPSID傳遞; -
token || admintoken:用戶登錄授權(quán)或管理員登錄授權(quán)都可以;
圖片 -
sign:需要簽名,一般用于服務(wù)端內(nèi)部相互調(diào)用,詳見[ API HMAC-SHA1簽名]({% post_url 2017-11-08-API-HMAC-SHA1-Sign %})。
-
狀態(tài)碼說明
正確
接口正常訪問情況下,服務(wù)器返回2××的HTTP狀態(tài)碼。
| HTTP狀態(tài)碼 |
|---|
| 200 OK - 表示已在響應(yīng)中發(fā)出、資源更改成功(GET、PUT) |
| 201 Created - 新資源被創(chuàng)建(POST) |
| 204 No Content - 資源被刪除(DELETE) |
錯誤
當用戶訪問接口出錯時,服務(wù)器會返回給一個合適的4××或者5××的HTTP狀態(tài)碼;以及一個application/json格式的消息體,消息體中包含錯誤碼code和錯誤說明message。
- 5××錯誤(
500=<status code)為服務(wù)器或程序出錯,客戶端只需要提示“服務(wù)異常,請稍后重試”即可,該類錯誤不在每個接口中列出。 - 4××錯誤(
400=<status code<500)為客戶端的請求錯誤,需要根據(jù)具體的code做相應(yīng)的提示和邏輯處理,message僅供開發(fā)時參考,不建議作為用戶提示。 - 部分錯誤示例:
| code | message | HTTP狀態(tài)碼 |
|---|---|---|
| InvalidToken | 未登錄或授權(quán)過期,請登錄 | 401 Unauthorized |
| ValidationError | 輸入字段驗證出錯,缺少字段或字段格式有誤 | 422 Unprocessable Entity |
| AccountNotExist | 賬戶名不存在 | 404 Not Found |
| InvalidPassword | 密碼錯誤 | 401 Unauthorized |
| NotFound | 請求的資源不存在 | 404 Not Found |
| AccountHasExist | 賬戶名已經(jīng)存在 | 409 Conflict |
| MobileHasBinded | 手機號已經(jīng)綁定其他賬戶 | 409 Conflict |
| InvalidSign | 參數(shù)簽名驗證未通過 | 403 Forbidden |
| InvalidSMSCode | 短信驗證碼錯誤 | 403 Forbidden |
| ExpiredSMSCode | 過期的短信驗證碼 | 403 Forbidden |
| FrequencyLimit | 發(fā)送過于頻繁,請稍后再試 | 403 Forbidden |
| TimesExceeded | 達到最大發(fā)送次數(shù)限制,請明天再試 | 403 Forbidden |
| VerifyTimesExceeded | 達到最大校驗次數(shù),請明天再試 | 403 Forbidden |
| RateLimitExceeded | 接口調(diào)用次數(shù)超過限制,請稍后再試 | 429 Too Many Requests |
| InternalError | 服務(wù)異常,請稍后再試 | 500 Internal Server Error |
參數(shù)傳遞
遵循RESTful規(guī)范,使用了GET, POST, PUT, DELETE共4種請求方法。
- GET:請求資源,返回資源對象
- POST:新建資源,返回新生成的資源對象
- PUT:新建/更新資源,返回完整的資源對象
- DELETE:刪除資源,返回body為空
- GET請求不允許有body, 所有參數(shù)通過拼接在URL之后傳遞,所有的請求參數(shù)都要進行遵循RFC 3986的URL Encode。
- DELETE刪除單個資源時,資源標識通過path傳遞,批量刪除時,通過在body中傳遞JSON。
- POST, PUT請求,所有參數(shù)通過JSON傳遞,可選的請求參數(shù),只傳有值的,無值的不要傳遞,contentType為application/json。
4種請求動作中,GET、PUT、DELETE是冪等的;只有POST是非冪等的。冪等操作的特點是其任意多次執(zhí)行所產(chǎn)生的影響均與一次執(zhí)行的影響相同。 是非冪等是判斷接口使用POST還是PUT的決定條件
注意: APP端獲取json數(shù)據(jù)時,對于數(shù)值類型字段必須以數(shù)值類型轉(zhuǎn)換,無論傳遞過來的值是否帶引號。


速率限制Rate Limiting
- 為了防止API被惡意調(diào)用,對API調(diào)用進行速率限制。
- 速率限制為每IP每15分鐘5000次(dev/qa為10W)調(diào)用(15分鐘是一個時間窗口)。
- 限制是針對所有接口模塊一起計算的(Redis key為
APIRL:{IP}),暫時沒有特殊的模塊或單個接口(未來可能有)。 - 你可以通過每個接口返回的HTTP headers了解當前速率限制的情況:
- X-RateLimit-Limit: 每個IP每個時間窗口最大請求數(shù)
- X-RateLimit-Remaining: 當前時間窗口剩余請求數(shù)
- X-RateLimit-Reset: 下次更新時間窗口的時間(UNIX時間戳),達到下個時間窗口時,Remaining恢復為Limit
-
超出速率限制,返回以下錯誤
圖片
安全注意事項
- 用戶登錄后用戶的token;aliyun OSS的bucket、AccessKey ID與AccessKey secret;微視頻的appid、sign、bucket;這些關(guān)鍵數(shù)據(jù)通過調(diào)用接口獲得,需要在客戶端以安全的方式存儲。
- 音頻視頻在APP內(nèi)的存儲,不允許被拷貝(即使越獄或root后拿走也無法使用)。
測試工具
推薦Chrome瀏覽器插件Postman作為接口測試工具,
Postman下載地址

文檔生成工具
- 生成的工具為apidoc,詳細閱讀官方文檔:http://apidocjs.com
調(diào)用示例
-
偽代碼
圖片 -
PHP
圖片
API模塊信息獲取
- App配置文件中僅存儲api模塊名,App初始化時請求獲取api模塊信息,獲取各個api模塊的信息(endpoint和version)。




