1、說明
在整個(gè)文檔中,會(huì)有一些對(duì)于標(biāo)準(zhǔn)和實(shí)踐的推薦和建議。一些實(shí)踐是非常重要的,必須嚴(yán)格執(zhí)行,另一些指導(dǎo)準(zhǔn)則并不一定處處適用,但是會(huì)在特定的場(chǎng)景下帶來益處。為了清楚陳述規(guī)范和實(shí)踐的意圖,我們會(huì)使用如下術(shù)語。
2、通用命名約定
見 命名指南 中的”Restful接口”章節(jié),不一致時(shí)以本文檔為準(zhǔn)。
3、基本設(shè)計(jì)規(guī)范
3.1 關(guān)注點(diǎn)分離 ★
設(shè)計(jì)的時(shí)候盡量保持簡(jiǎn)單,一定要分離請(qǐng)求和響應(yīng)時(shí)關(guān)注的不同部分,如:URL、Method、HEADER、body、HTTP Status Codes
3.2 使用HTTPS★
- 外部服務(wù)一定要使用TLS(就是HTTPS)來訪問API,沒有必要指出什么時(shí)候需要用,什么時(shí)候不需要用,只管任何時(shí)候都用它;
- 內(nèi)部服務(wù)應(yīng)該使用TLS,當(dāng)前階段不作為強(qiáng)制規(guī)范;
- 對(duì)所有非TLS的請(qǐng)求返回403 Forbidden,不要用重定向,這會(huì)允許一些不良的客戶端行為,而又沒有任何好處。依賴重定向的客戶端會(huì)使流量翻倍,而讓TLS毫無意義 — 敏感數(shù)據(jù)已經(jīng)在第一次請(qǐng)求時(shí)發(fā)送出來了。
3.3 版本化API ★
REST版本化和多版本間過渡,是RESTful架構(gòu)設(shè)計(jì)和運(yùn)行時(shí)的挑戰(zhàn)。因此,最好在一開始就考慮版本。
- 一定要在PATH上定義接口版本,如:
- 如果需要A/B Test,一定要在Request Header上定義,詳見Requests設(shè)計(jì)規(guī)
- 一定不要提供默認(rèn)版本,而由客戶端顯式指定它使用哪一個(gè)特定的版本。
3.4 RequestId追溯★
每個(gè)API請(qǐng)求一定要包含一個(gè)唯一的UUID
UUID存放在HEAD的X-OHM-Request-Id中,用來追溯。 由客戶端,服務(wù)器和任何后端服務(wù)上記錄這些值。 當(dāng)出現(xiàn)問題時(shí),根據(jù)這個(gè)值可以更容易地找出問題并更迅速地提供解決方案。它提供了一種機(jī)制來跟蹤,診斷和調(diào)試REST請(qǐng)求。
3.5權(quán)限分離★
一定要通過url****和端口區(qū)分公共、私有、管理api,如:
- 公共(public):https://xxx.xxx.com/upp/v1/ 【可選端口:80,8000-8999】
- 私有(private):https://internal.xxx.xxx.com:9000/v1/ 【可選端口:9000-9899】
- 管理(admin):https://admin.xxx.xxx.com:9900/v1/【可選端口:9900-9999】
3.6 Etags緩存
可以在所有的請(qǐng)求中帶上 ETag 頭 ,用于識(shí)別返回資源的特定版本。用戶可以在隨后的請(qǐng)求中通過提供If-None-Match頭的值來檢查內(nèi)容是否需要更新。
3.7 Ranges分頁
可以對(duì)所有可能產(chǎn)生大量數(shù)據(jù)的響應(yīng),可以使用Content-Range頭來標(biāo)記分頁請(qǐng)求。
3.8過濾、選擇、排序
**過濾 Filtering **:
使用唯一的查詢參數(shù)進(jìn)行過濾:
curl +X GET https://xxx.xxx.com/v1/cars?color=red 返回紅色的cars
curl +X GET https://xxx.xxx.com/v1/cars?seatsTo=2 返回小于兩座位的cars集合
選擇 Field selection
移動(dòng)端能夠顯示其中一些字段,它們其實(shí)不需要一個(gè)資源的所有字段,給API消費(fèi)者一個(gè)選擇字段的能力,這會(huì)降低網(wǎng)絡(luò)流量,提高API可用性。
curl +X GET https://xxx.xxx.com/v1/cars?fields=manufacturer,model,id,color
排序 Sorting :
允許針對(duì)多個(gè)字段排序
curl +X GET https://xxx.xxx.com/v1/cars?sort=-manufactorer,+model
這是返回根據(jù)生產(chǎn)者降序和模型升序排列的car集合
4 請(qǐng)求Requests設(shè)計(jì)規(guī)范
4.1 資源名 ★
-
一定使用名詞而不是動(dòng)詞
- curl +X GET https://xxx.xxx.com/v1/users/{userId}
- curl +X GET https://xxx.xxx.com/v1/getUserByID
-
一定使用復(fù)數(shù)名詞
- /users y/user
- /users/{userId}/apps y/user/{userId}/app
- 使用資源名稱的復(fù)數(shù)版本除非有關(guān)資源是在系統(tǒng)內(nèi)的單(例如,系統(tǒng)的整體狀態(tài)可能是/status)。這使得它在你提到的特定資源的方式是一致的。
4.2 請(qǐng)求頭★
Host: xxx.xxx.xxx.com
Date: Mon, 22 Aug 2016 11:21:04 GMT
User-Agent: Apache-HttpClient/4.1.2 (java 1.6)
**Content-Type: application/x-www-form-urlencoded; charset=UTF-8 **
//請(qǐng)求體類型,請(qǐng)根據(jù)實(shí)際請(qǐng)求體內(nèi)容設(shè)置
Accept: application/json
//請(qǐng)求響應(yīng)體類型,部分API可以根據(jù)指定的響應(yīng)類型來返回對(duì)應(yīng)數(shù)據(jù)格式,建議手動(dòng)指定此請(qǐng)求頭,如果不設(shè)置,部分HTTP客戶端會(huì)設(shè)置默認(rèn)值/,導(dǎo)致簽名錯(cuò)誤
X-OHM-App-Version: 1.0.0.2a
//APP版本號(hào),用于請(qǐng)求路由、A/B Test等場(chǎng)景
X-OHM-Stage: RELEASE
//請(qǐng)求API的Stage,如TEST、RELEASE,API提供者可以選擇發(fā)布到哪個(gè)Stage,只有發(fā)布到指定Stage后API才可以調(diào)用,否則會(huì)提示API找不到/Invalid Url/簽名失敗等錯(cuò)誤
X-OHM-ClientKey: 60022326
//請(qǐng)求的AppKey,只有獲得API授權(quán)后才可以調(diào)用
X-OHM-Time: 2016-04-06T12:00:00Z
//請(qǐng)求時(shí)間戳
**X-OHM-RequestId(必須): 7AD052CB-EE8B-4DFD-BBAF-EFB340E0A5AF **
//請(qǐng)求唯一標(biāo)識(shí),UUID,建議15分鐘內(nèi)Request-Id不能重復(fù),與時(shí)間戳結(jié)合使用起到防重放作用
X-OHM-Signature: FJleSrCYPGCU7dMlLTG+UD3Bc5Elh3TV3CWHtSKh1Ys=
//請(qǐng)求簽名,用于驗(yàn)簽,防止偽造請(qǐng)求,根據(jù)接口的安全等級(jí)自定義規(guī)則,一般httpmethod、header、body、url的重要信息都要包含
X-OHM-UserId:
** X-OHM-UserToken:**
//用戶Id和Token
X-OHM-Request-Mode:Debug
//是否開啟Debug模式,不設(shè)置默認(rèn)關(guān)閉,一般API調(diào)試階段可以打開此設(shè)置,打開會(huì)接口會(huì)返回更相信的deug信息;生產(chǎn)上不允許打開。
X-{產(chǎn)品代碼}-XXX
//自定義請(qǐng)求頭,如X-UPP-XXX
4.3 操作
一般CRUD操作不需要定義在url中,但如果需要一些特殊的操作可以用actions作為path
示例:/apps/{appId}/actions/start
4.4 正確使用http method ★
僅使用以下四個(gè)方法:POST/GET/PUT/DELETE
4.5 少用路徑嵌套★
數(shù)據(jù)模型可能有父子嵌套關(guān)系,路徑可能深度嵌套
示例:https://xxx.xxx.com/v1/users/{userId}/apps/{appId}/docker/{dockerId}
寧愿在根路徑上限制資源嵌套,使用嵌套來表示作用域的集合
例如:一個(gè)docker屬于一個(gè)應(yīng)用,一個(gè)應(yīng)用屬于一個(gè)用戶
示例:
[https://xxx.xxx.com/v1/users/{userId](https://xxx.xxx.com/v1/users/%7BuserId)}
[https://xxx.xxx.com/v1/users/{userId}/apps](https://xxx.xxx.com/v1/users/%7BuserId%7D/apps)
[https://xxx.xxx.com/v1/apps/{appId](https://xxx.xxx.com/v1/apps/%7BappId)}
[https://xxx.xxx.com/v1/apps/{appId}/dockers](https://xxx.xxx.com/v1/apps/%7BappId%7D/dockers)
[https://xxx.xxx.com/v1/dockers/{dockerId](https://xxx.xxx.com/v1/dockers/%7BdockerId)}
5 響應(yīng)Responses設(shè)計(jì)規(guī)范
5.1 返回適當(dāng)?shù)臓顟B(tài)碼 ★
rfc7231#section-6中的定義:
- 1xx (Informational): The request was received, continuing process
- 2xx (Successful): The request was successfully received, understood, and accepted
- 3xx (Redirection): Further action needs to be taken in order to complete the request
- 4xx (Client Error): The request contains bad syntax or cannot be fulfilled
- 5xx (Server Error): The server failed to fulfill an apparently valid request
成功的響應(yīng)一定要從以下返回碼中進(jìn)行選擇:
- 200 OK: 請(qǐng)求GET調(diào)用成功,對(duì)于DELETE方法同步調(diào)用完成,或?yàn)镻UT方法調(diào)用,同步更新現(xiàn)有資源
- 201: 請(qǐng)求POST調(diào)用成功,同步完成,或?yàn)镻UT調(diào)用同步創(chuàng)建了一個(gè)新的資源
- 202: 接受POST、PUT、DELETE請(qǐng)求,將異步處理請(qǐng)求結(jié)果
錯(cuò)誤的響應(yīng)一定要從以下返回碼中進(jìn)行選擇,特別注意400錯(cuò)誤,普通業(yè)務(wù)異常一定要返回400:
- 400 Bad Request:請(qǐng)求失敗,普通業(yè)務(wù)異常 & 服務(wù)器不理解請(qǐng)求語法
- 401 Unauthorized: 請(qǐng)求失敗,因?yàn)橛脩魶]有通過驗(yàn)證
- **403 ** Forbidden: 請(qǐng)求失敗,因?yàn)橛脩魶]有權(quán)限訪問特定資源
- 404 Not Found:請(qǐng)求失敗,未找到該資源
- 408 Request Timeout:請(qǐng)求超時(shí)
- 429 Too Many Requests:超頻調(diào)用,請(qǐng)稍后再試
- 500 Internal Server Error:服務(wù)器內(nèi)部錯(cuò)誤,檢查網(wǎng)站狀態(tài)或報(bào)告問題
5.2 UTC時(shí)間并用ISO8601格式化 ★
接受和返回時(shí)一定只用UTC時(shí)間,并用ISO8601格式化,如:
"finishedAt": "2016-04-06T12:00:00Z"
5.3 生成結(jié)構(gòu)化的錯(cuò)誤信息 ★
在報(bào)錯(cuò)時(shí)生成一致結(jié)構(gòu)的響應(yīng)請(qǐng)求,包括:
- code:一個(gè)機(jī)器可讀的錯(cuò)誤,
- message:一個(gè)人類可讀的錯(cuò)誤message,
- extraCode: 附加錯(cuò)誤碼,一般用于返回外部服務(wù)原始錯(cuò)誤碼, (可選)
- extraMessage: 附加錯(cuò)誤消息,一般用于返回外部服務(wù)原始錯(cuò)誤消息,(可選)
- tracestack:一個(gè)程序員可讀的錯(cuò)誤tracestack,(可選)
- url:一個(gè)url為客戶端提供進(jìn)一步錯(cuò)誤信息和解決方案(可選)
示例:
| |
[](https://docs.xxx.xxx.com/XXX)
|
6 文檔和其他(參考)
6.1 提供機(jī)器可讀的json schema
提供機(jī)器可讀的JSON schema來描述你的API,可以用prmd來管理JSON schema,用prmd verify來確保它通過驗(yàn)證
6.2 提供人類可讀的文檔
提供人類可讀的文檔幫助客戶端開發(fā)者們理解你的API。
如果你使用了prmd來創(chuàng)建schema,那么你可以簡(jiǎn)單的通過prmd doc命令來生成Markdown的endpoint級(jí)別的文檔。
除了endpoint級(jí)別的描述,還要提供概要級(jí)別的信息,
如:
- 授權(quán),包括獲得和使用授權(quán)Token。
- API的穩(wěn)定性和版本,包括如何選擇現(xiàn)有的API版本。
- 通用請(qǐng)求和響應(yīng)頭。
- 錯(cuò)誤的序列化格式。
- 各種語言的客戶端如何使用API的例子。
6.3 提供可執(zhí)行的示例
提供可執(zhí)行的例子,這樣用戶可以直接在終端輸入并看到可以用的API請(qǐng)求。最好的情況是,這些例子可以直接復(fù)制粘貼,以最小化用戶試用API的成本,
如:
$ export TOKEN=... # acquire from dashboard
$ curl -is https://$TOKEN@xxx.xxx.com/v1/users
如果你使用prmd來生成Markdown文檔,免費(fèi)獲得了可執(zhí)行的示例。
6.4 提供mockapi
[圖片上傳失敗...(image-b07de4-1526024018097)]
6.5 描述穩(wěn)定性
描述你API的穩(wěn)定性,以及哪些endpoint依賴于其成熟度,比如使用prototype,development或者production的標(biāo)識(shí)。
可參考 Heroku API compatibility policy 了解哪些接口是穩(wěn)定的,哪些可能有變動(dòng)。
一旦你的API宣布為 production-ready 和 穩(wěn)定版,不要在該API版本上做任何不向前兼容的修改。如果你需要做不向前兼容的修改,創(chuàng)建一個(gè)新的版本號(hào)。
[圖片上傳失敗...(image-c70619-1526024018097)]