大前端前提下,開發采用前后端分離的方式,前端和后端主要通過接口進行分離,
后端開發接口,前端使用接口,前后端接口開發告一段落以后,接口聯調差不多就進入開發尾聲,准備送測了。
那么,對接口的約束和規范就尤為重要,以下文檔是我負責參與技術委員會,
基於restful架構制定的web接口規范。具體內容如下:
需要確認的問題列表:
序號
|
是否完成
|
問題說明
|
解決方案
|
---|---|---|---|
1 |
|
URL路徑/api/xxx,his/,這一塊的表現形式 | 已經補充 至: 2.1.1.3. 路徑中優先體現服務和資源 |
2 |
|
URL路徑命名規范,動詞放前面還是后面 | 已經補充 至: 2.1.1.4. URL路徑命名規范 |
3 |
|
版本號問題如何解決 | |
4 |
|
query非業務數據不傳,解決方法 | |
5 |
|
請求方法,是強制2個,還是5個 | |
6 |
|
lang 返回語言,這個字段怎么設計(JSON數據類型?) | 多語言設計,是需要繼續探討的。第一版規范暫時不包含。 |
7 |
|
||
8 |
|
《公司應用錯誤碼規范》 |
|
9 |
|
補充request-id | 已經補充 至: 2.3. 請求首部 Request Headers |
10 |
|
業務異常,返回狀態碼問題 | 和xx又討論一下次,結論整理如下: 1. 將異常分為3個類型:用戶錯誤請求異常(BadRequestException)、系統異常(Exception)、業務異常(ServiceException) 2. 業務異常,http status 使用 200,返回數據內部區分具體不同 {code, message} 3. 系統異常,http status 使用 500,返回數據 = {code: 特定編碼, message: 一句友好的提示, errorInfo: 用於定位問題(可能有堆棧信息);未了避免返回敏感信息,在正式環境將屏蔽} 4. 用戶錯誤請求異常,https status 使用 400, 返回數據 = {code: 特定編碼,message: 錯誤原因,用於輔助前端同學調整或者參加參數校驗} 5. 接口請求中如果出現 400 或 500,開發、測試同學一定要關注。500問題由后端同學處理;400問題由前端同學處理。 |
1. 概述
1.1. 背景及目的
為了更好的提高前后端協同開發效率,降低維護難度,有必要對接口進行規范。基於目前公司現狀,本規范旨在統一前后端之間、及各業務系統之間HTTP API接口調用與交互。
1.2. 適用范圍
所有新上線服務的內網/外網HTTP/HTTPS接口,建議舊系統再改造上線過程中也參照逐步向本規范靠攏,最終達到所有系統HTTP接口都按統一規范定義。
1.3. 描述方式約定
【強制】表示該條規則必須遵守,【推薦】表示該條規則大多數情況下遵守,是建議性規則
每個大的規則下只要有一條子規則是【強制】規則,這條大規則會標記為【強制】,但並不表示該大規則下的其它【推薦】子規則也是【強制】
1.4. 結構說明
為了方便理解,以下內容按照chrome中network結構進行說明:
2. 請求報文 Headers
2.1. 常規項 General
2.1.1. 請求地址 Request URL
https:
//
域名:port
/api/user-center/customers?limit=25&offset=50&fields=id,name,age
2.1.1.1. 協議方案名
使用http:或https:等協議方案名獲取訪問資源時要指定協議類型。
2.1.1.2. 域名,端口
每個業務使用的域名會有差異。北吉熊使用的域名是 power.medcloud.cn
一般的web接口,向前端暴露的,只用80端口,平時本地調試使用的端口不做限制。
2.1.1.3. URL路徑中優先體現服務和資源
api/user-center/customers
這個例子中,user-center是服務名稱,而customers代表資源名稱。不要在api/和user-center/之間再添加其他部分。
描述要盡量簡短,也要清晰地體現其定位和差異,避免未來其他服務或資源出現重名。
2.1.1.4. URL路徑命名規范
正確示例:/api/user-center/customers/43
一般的接口,不要在路徑中添加動詞,因為大部分的操作行為,都通過HTTP Method來表示了。
獲取多個客戶,數據集合:
METHOD: GET
/api/user-center/customers?current=
16
&size=
20
&fields=id,name,age
|
獲取某個客戶的所有訂單:
METHOD: GET
/api/user-center/customers/
448207
/orders
|
參考依據:微軟Azure接口設計 , http-api-design-ZH_CN, HTTP API Design
2.1.1.4.1.【強制】路徑名稱只能包含小寫英文字母、數字和短划線,且第一個字符必須是小寫英文字母,單詞之間用短划線分隔;
正確示例:
|
錯誤示例:
|
2.1.1.4.2.【強制】使用名詞表示資源,只有在名詞無法表示接口含義時,才使用動詞作為補充的action動作
獲取單個客戶:
METHOD: GET
/api/user-center/customers/
448207
|
某些特殊情況下,需要指定動作,可以添加動詞。如非必要,還是別用。
對某個客戶做重置操作:
METHOD: GET
/api/user-center/customers/
448207
/actions/reset
|
2.1.1.4.3.【推薦】URL路徑末尾建議不加.json等后綴,比如.xml, .htm等都不建議。(文件名本身帶有后綴名的靜態文件URL路徑不在本規范的限制內)
2.1.1.5. 版本號
【強制】在Request Header中標識版本號。
// 通過自定義頭設置版本1
X-Api-Version:
1
// 通過自定義頭設置版本2
X-Api-Version:
2
// 通過自定義頭設置版本2.1
X-Api-Version:
2.1
|
注意:不要在path中添加版本號。版本是指接口的版本(對應Java代碼中某個具體方案),不是整個服務的版本。
2.1.1.6. 數據變量
接口請求和響應數據中的變量名用小駝峰命名。
接口請求和響應數據中的變量名只能包含大小寫字母、數字,變量中每個單詞首字符必須是字母,第一個單詞首字母必須是小寫字母,其它單詞首字母必須大寫,單詞之間無分隔字符。
正確示例:companyLicenceRegNo 小駝峰命名方式
錯誤示例:CompanyLicenceRegNo、companylicenceRegNo、company_LicenceRegNo、company_licence
正確示例:?userName=xxxx&password=xxxxx
錯誤示例:?user_name=xxxx&Password=xxxxx
錯誤示例:?username=xxxx&password=xxxxx
錯誤示例:?UserName=xxxx&password=xxxxx
2.1.1.7. 避免傳遞無關參數
北吉熊系統中很多接口都要傳一些通用參數,這些參數比較冗余,很多時候,后端服務通過token都能查出來。
要盡量避免無用參數的傳遞。
另外,在支持cookie的瀏覽器中,也要通過服務端程序寫token,就不需要前端顯式地傳遞了
2.1.1.8. URL最大長度限制為2083字節
【強制】URL最大長度限制為2083字節,包含?問號后面的query部分。(IE 2083, chrome 8182, firefox 65536, Safari 80000, Opera 190000)
2.1.1.9. 規定字段必須按照規范命名
【強制】涉及以下參考表中的字段必須按參考表中的名稱命名,字段層級和數據類型格式要符合參考表說明的格式要求。
通用命名字段參考《HTTP通用命名參數》:
字段名
|
JSON數據類型
|
字段含義
|
備注
|
---|---|---|---|
current | Number | 查詢的頁碼,以1為第一頁 | 僅分頁場景【強制】 |
size | Number | 查詢的分頁大小,默認10 | 僅分頁場景【強制】 |
medicalInstitutionId | String | 機構ID | 所有ID類的字段,如果后端是Long類型,傳給前端,必須用字符串,不能以數字形式傳遞。 |
chainMedicalInstitutionId | String | 連鎖機構ID | |
patinetId | String | 患者ID | |
其它后續討論補充 |
2.1.2. 請求方法 Request Method
常用的HTTP動詞有下面五個(括號里是對應的SQL命令)。
【強制】每一個HTTP接口,實現時必須明確指定允許的HTTP Method,不允許默認。
【強制】HTTP Method用途分類的規定,示例:《HTTP Method 代碼示例》、《HTTP Method 報文示例》。
方法名稱 | 說明 | 舉例 | 規范 | |
---|---|---|---|---|
【強制】GET(SELECT) | 從服務器取出資源(一項或多項) | 查詢業務數據列表,查詢業務數據詳情 /api/user-center/customers?limit=25&offset=50&fields=id,name,age /api/user-center/customers/448207 /api/user-center/customers/448207/orders |
query上送 (空值規范,為空不傳,注意編碼和解碼) |
|
【推薦】DELETE(DELETE) | 從服務器刪除資源 | 刪除指定數據 /api/user-center/customers/448207 |
||
【強制】POST(CREATE) | 新建一個資源 |
新增業務數據,比如:發起交易(生成新交易),用戶注冊,用戶登錄 以下是添加一個客戶 /api/user-center/customers/
|
JSON格式字符串作為HTTP BODY上送 (文件上傳接口除外) |
|
【推薦】PUT (CREATE或UPDATE) | 新建或更新資源,如果存在,就更新,如果不存在,就新建。客戶端可提供有變更的字段,但必須有唯一性標識,可以在路徑中表示。 |
以下是添加或創建一個客戶,路徑特殊之處在於,帶了id /api/user-center/customers/448207
|
||
【推薦】PATCH(UPDATE) | 在服務器更新資源(客戶端提供改變的屬性) |
客戶端上傳部分字段數據,可以理解為對數據打個小補丁。特殊之處在於,字段只包含變更了的,沒變更的字段不包含進JSON數據中。 /api/user-center/customers/448207
|
以下內容是對上表的詳細說明:
- 五個方法,兩個強制,三個推薦
- 【強制】GET和DELETE請求數據使用查詢參數(query) 傳
- 【強制】POST/PUT/PATCH請求數據采用JSON格式字符串作為HTTP BODY提交,文件上傳接口除外;
- 【推薦】文件上傳接口允許使用表單提交(application/x-www-form-urlencoded或者multipart/form-data),UTF-8編碼格式,可以增加一個MD5校驗值參數,MD5校驗無需鹽值。
- 【推薦】需要支持探活的接口,實現時必須支持Method為HEAD的請求
- 【強制】請求HTTP HEADER中用"Content-Type"指明請求數據格式,使用"Accept"指明期望返回的數據格式,
示例1(請求數據格式和期待響應數據格式都是JSON):
|
示例2(請求數據格式表單,期待響應數據格式為JSON):
|
7.【推薦】JSON請求和響應數據中的空值規范
本條的目的:為了簡化前端判斷邏輯,減少字段有無的判斷和類型判斷。數據字段不存在等同於Java對象中該字段值為空指針null
【推薦】請求數據中非必填JOSN字段不存在時,則不填該字段,適用於所有JSON類型。
【推薦】響應數據中非必填JOSN字段不存在時,則不填該字段,適用於所有JSON類型。
2.1.3. 狀態碼 Status Code
【推薦】按照HTTP協議對STATUS狀態碼的定義,不同情況返回適當的狀態碼,但禁止使用HTTP STATUS狀態碼來表示業務邏輯的不同結果,比如:用戶不存在時也應返回200,而不是404。
【強制】權限驗證不通過時,必須返回403狀態碼,以便於框架模塊統一截獲作適當的處理。了解更多詳情《HTTP STATUS 狀態碼》
服務器向用戶返回的狀態碼和提示信息,常見的有以下一些(方括號中是該狀態碼對應的HTTP動詞)
- 200 OK - [GET]:服務器成功返回用戶請求的數據,該操作是冪等的(Idempotent)。
- 201 CREATED - [POST/PUT/PATCH]:用戶新建或修改數據成功。
- 202 Accepted - [*]:表示一個請求已經進入后台排隊(異步任務)
- 204 NO CONTENT - [DELETE]:用戶刪除數據成功。
- 400 INVALID REQUEST - [POST/PUT/PATCH]:用戶發出的請求有錯誤,服務器沒有進行新建或修改數據的操作,該操作是冪等的。
- 401 Unauthorized - [*]:表示用戶沒有權限(令牌、用戶名、密碼錯誤)。
- 403 Forbidden - [*] 表示用戶得到授權(與401錯誤相對),但是訪問是被禁止的。
- 404 NOT FOUND - [*]:用戶發出的請求針對的是不存在的記錄,服務器沒有進行操作,該操作是冪等的。
- 406 Not Acceptable - [GET]:用戶請求的格式不可得(比如用戶請求JSON格式,但是只有XML格式)。
- 410 Gone -[GET]:用戶請求的資源被永久刪除,且不會再得到的。
- 422 Unprocesable entity - [POST/PUT/PATCH] 當創建一個對象時,發生一個驗證錯誤。
- 500 INTERNAL SERVER ERROR - [*]:服務器發生錯誤,用戶將無法判斷發出的請求是否成功。
狀態碼的完全列表參見這里。
2.2. 響應首部 Response Headers
Content-Type
Accept
合並到
2.1.2
2.3. 請求首部 Request Headers
Content-Type 和
Accept
請參考
2.1.2
在請求頭中,還需要添加 Request-Id,以方便后端查日志查問題。其值為UUID。
X-Request-Id: 7c129eb1-c479-47bb-9c73-d263e2673026
|
2.4. 傳參 Query / Body (form data)
合並到 2.1.2. 請求方法 Request Method
3. 響應 Response
響應json結構如下圖:
3.1.【強制】響應數據格式規范
3.1. 1.【強制】響應數據使用JSON格式
3.1. 2. 【強制】響應數據JSON格式要求:code、msg和data必須是0級字段,_st、code必填字段,code != 0 (失敗)時msg必填。
3.1. 3. 【強制】響應數據用JSON String類型表示Java Long類型數據
3.1. 4. 【強制】涉及以下參考表中的字段必須按參考表中的名稱命名,字段層級和數據類型格式要符合參考表說明的格式要求,
通用字段命名參考:
字段名 | 字段層級 | JSON數據類型 | 字段含義 | 備注 |
---|---|---|---|---|
_st | 0 | Number | 服務器時間 |
【強制】必須嚴格符合《公司應用錯誤碼規范》
|
code | 0 | Number | 響應結果狀態/錯誤碼 0:表示成功 非0:表示失敗 |
|
msg(但his系統的錯誤描述為message) | 0 | String | 錯誤描述(外部描述) 非0時,返回msg。 |
|
lang(his系統有,scrm系統沒有) |
0 | String | 語言 | |
data | 0 | Object | 響應業務數據 |
|
data.current | 1 | Number | 分頁頁碼,以1為第一頁 | 僅分頁場景【強制】 |
data.size | 1 | Number | 分頁大小 | 僅分頁場景【強制】 |
data.pages | 1 | Number | 總頁數 | 僅分頁場景【強制】 |
data.total | 1 | Number | 總記錄數 | 僅分頁場景【強制】 |
data.records | 1 | Array | 數據列表 | 僅分頁場景【強制】 |
其它后續討論補充 |
3.1.5 【強制】錯誤碼字段及格式定義必須符合《公司應用錯誤碼規范》
正確示例:
{
"_st"
: 1620133767482,
"code"
: 407,
"msg"
:
"機構異常"
}
|
正確示例:
{
"_st"
: 1619781822535,
"code"
: 0,
"data"
: {
"appointmentBeginTime"
: 1619917200000,
"appointmentEndTime"
: 1619919000000,
"appointmentId"
: 5810,
"appointmentMemo"
:
"1111111111111121111"
,
"appointmentReason"
:
"121"
,
"appointmentStatus"
: 6,
"arrearsFlag"
:
false
,
"birthday"
:
"1999-04-30"
,
"doctorId"
: 4800,
"doctorName"
:
"大白醫生"
,
"patientAge"
:
"22"
,
"patientGender"
: 1
}
}
|
正確示例:
{
"_st"
: 1619781822535,
"code"
: 0
}
|
4. 其他規范 Other
4.1.【強制】HTTP HEADER命名規范
4.1 .1【強制】自定義HTTP HEADER名稱必須由大小寫字符、數字和連字符-構成,必須以 "X-" 為前綴,單詞之間用"-"連字符分隔,每個單詞首字符必須是大寫字母(不能是數字),其它字母小寫,但單詞本身是首字母簡稱的則全部大寫,比如:X-Salt-Version,X-AES-Key,X-UUID-*
4.1.2【推薦】涉及以下參考表中的Header的必須按參考表中的名稱命名,格式要符合參考表說明的格式要求。
自定義HEADER名稱參考:
HEADER名稱
|
用途
|
字段值格式
|
可選說明 |
備注
|
---|---|---|---|---|
X-Token | 訪問令牌 | 字符串 | ||
X-Refresh-Token | 刷新令牌,通常不傳輸,用於令牌刷新相關操作 | |||
X-Salt-Version | 當前數據簽名使用的salt鹽值版本 | 字符串 | 比如: X-Salt-Version: 1 |
|
X-Key-Version | 當前數據加密使用的加密密鑰版本 | 字符串 "加密算法-密鑰版本" |
比如: X-Key-Version: aes-001 |
|
X-Timestamp | 請求/響應時間戳,簽名用做nonce隨機值 | |||
X-Sign | 簽名(值) | 字符串 |
4.2. 傳輸規范
4.2.1.【強制】傳輸協議規范
4.2.1.1 【推薦】內網接口采用HTTP傳輸,端口號不得以*443結尾,比如不使用8443,7443等端口(容易觸發部分軟件中的BUG);除中間件等特殊開源軟件外,內網HTTP接口一般用8080端口;
4.2.1.2 【強制】外網接口除特殊情況外必須采用HTTPS傳輸,特殊情況的必須備案登記,並經技術委員會特例審批。外網HTTPS必須使用默認端口號443,外網HTTP必須80端口
4.2.2. 【強制】HTTP GZIP壓縮傳輸規范說明
壓縮傳輸時采用HTTP協議標准定義的方式進行,本條規范僅僅時對協議標准的解釋說明,但XX科技僅限使用GZIP壓縮數據格式,不能使用deflate(ZLIB)等其它格式,以簡化各系統實現。
客戶端在請求HTTP Header中用 Accept-Encoding: gzip,明確告知服務端,本客戶端支持的壓縮格式
服務端在響應HTTP Header中用 Content-Encoding:gzip 指示客戶端需要對內容進行GZIP解壓縮,也可以返回未壓縮的內容,如果內容沒有壓縮時,禁止返回Content-Encoding
響應HTTP Header中Content-Type指明壓縮前的內容格式,如: Content-Type: application/json;charset=UTF-8
響應HTTP Header中Content-Length指明壓縮后的內容長度
HTTP/1.1 協議中的壓縮格式說明表:
格式標識名
|
格式說明
|
備注
|
---|---|---|
gzip | GZIP數據格式 | RFC 1952
|
deflate | ZLIB數據格式 | RFC 1950 RFC 1951(IE瀏覽器) |
4.3. 接口安全相關規范
4.3.1.【強制】簽名規范
4.3.1.1.【強制】簽名采用SHA256算法,新系統一律禁止使用MD5簽名
4.3.1.2.【強制】簽名運算時必須要有SaltKey鹽值和nonce隨機值參與運算,即SHA256(plainText+saltKey+nonce),以便同時滿足防篡改和防重放攻擊的作用。
4.3.1.3.【強制】內網服務間接口除非特殊要求外,不進行簽名和驗簽。
4.3.1.4.【推薦】公網接口要求簽名和驗簽。
4.3.1.5.【推薦】簽名和驗簽過程建議在業務網關側處理,不建議在內部業務系統中處理簽名和驗簽。
4.3.1.6. 【強制】簽名SaltKey鹽值必須支持平滑更換要求。
4.3.1.7.【推薦】簽名SaltKey鹽值平滑更換方式,建議通過在HTTP Header中指定"X-Salt-Version: xxx"指明當前鹽值版本,來支持鹽值過渡。
4.3.2.【強制】敏感數據加密規范
4.3.2.1 【強制】對於密碼和密鑰類極度敏感數據必須采用RSA非對稱加密算法加密,RSA密鑰的長度必須大於1024。
4.3.2.2.【強制】接口請求和響應中的普通數據加密要求采用AES對稱加密算法。
4.3.2.3 【推薦】外網接口請求和響應中的一般敏感數據推薦在網關則統一對整個Body加解密。
4.3.2.4 【強制】加密密鑰支持平滑更換要求。
4.3.2.5 【推薦】加密密鑰平滑更換方式,建議通過在HTTP Header中指定"X-Key-Version: aes-xxx" 指明當前密鑰版本,來支持密鑰過渡。
4.3.3.【強制】登錄接口特殊要求
4.3.3.1. 【強制】外網接口禁止使用Http Basic認證(因為是base64(用戶名:密碼) 明文傳輸)。
4.3.3.2. 【強制】密碼禁止明文傳輸(包括明文Base64轉換后的值),只能傳密碼的SHA256摘要,或者非對稱加密后的密文。
4.4.4. 【強制】接口相關的Cookie使用規范
4.4.4.1. 【強制】Cookie必須加上Secure和HttpOnly屬性,必須設置有效期。
HTTP HEADER 示例:
Set-Cookie: key=value; Expires=date; Path=path; Domain=domain; Secure; HttpOnly
|
參考文檔
https://geemus.gitbooks.io/http-api-design/content/en/requests/downcase-paths-and-attributes.html
https://tools.ietf.org/html/rfc2616
https://tools.ietf.org/html/rfc1738
https://tools.ietf.org/html/rfc2396
https://tools.ietf.org/html/rfc3986
https://tools.ietf.org/html/rfc7159
https://tools.ietf.org/html/rfc8259
https://docs.microsoft.com/en-us/azure/architecture/best-practices/api-design