RestFul設(shè)計(jì)規(guī)范

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★

  1. 外部服務(wù)一定要使用TLS(就是HTTPS)來訪問API,沒有必要指出什么時(shí)候需要用,什么時(shí)候不需要用,只管任何時(shí)候都用它;
  2. 內(nèi)部服務(wù)應(yīng)該使用TLS,當(dāng)前階段不作為強(qiáng)制規(guī)范;
  3. 對(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)。因此,最好在一開始就考慮版本。

  1. 一定要在PATH上定義接口版本,如:
    1. https://xxx.xxx.com/upp/cpg/v1
    2. https://xxx.xxx.com/upp/cpg/v2
  2. 如果需要A/B Test,一定要在Request Header上定義,詳見Requests設(shè)計(jì)規(guī)
  3. 一定不要提供默認(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,如:

  1. 公共(public):https://xxx.xxx.com/upp/v1/ 【可選端口:80,8000-8999】
  2. 私有(private):https://internal.xxx.xxx.com:9000/v1/ 【可選端口:9000-9899】
  3. 管理(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 資源名 ★

  1. 一定使用名詞而不是動(dòng)詞
    1. curl +X GET https://xxx.xxx.com/v1/users/{userId}
    2. curl +X GET https://xxx.xxx.com/v1/getUserByID
  2. 一定使用復(fù)數(shù)名詞
    1. /users y/user
    2. /users/{userId}/apps y/user/{userId}/app
  3. 使用資源名稱的復(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)]

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,569評(píng)論 19 139
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,063評(píng)論 25 709
  • 去年有段時(shí)間得空,就把谷歌GAE的API權(quán)威指南看了一遍,收獲頗豐,特別是在自己幾乎獨(dú)立開發(fā)了公司的云數(shù)據(jù)中心之后...
    騎單車的勛爵閱讀 21,116評(píng)論 0 41
  • 21.離婚 隔壁老王已經(jīng)快50歲了,為生第三胎經(jīng)常跟他老婆吵架,只因前面兩胎都是女兒。老王覺得很沒面子,在親戚面前...
    默夜清輝閱讀 448評(píng)論 0 0
  • gulp使用流程:安裝nodejs -> 全局安裝gulp -> 項(xiàng)目安裝gulp以及gulp插件 -> 配置gu...
    liuwan閱讀 1,754評(píng)論 0 0

友情鏈接更多精彩內(nèi)容