MVVM前后端分离:web接口规范

 

大前端前提下,开发采用前后端分离的方式,前端和后端主要通过接口进行分离,

后端开发接口,前端使用接口,前后端接口开发告一段落以后,接口联调差不多就进入开发尾声,准备送测了。

那么,对接口的约束和规范就尤为重要,以下文档是我负责参与技术委员会,

基于restful架构制定的web接口规范。具体内容如下:

 

  • 1.  概述
    • 1.1. 背景及目的
    • 1.2.  适用范围
    • 1.3.  描述方式约定
    • 1.4. 结构说明
  • 2. 请求报文 Headers
    • 2.1. 常规项 General
      • 2.1.1. 请求地址 Request URL
        • 2.1.1.1. 协议方案名
        • 2.1.1.2. 域名,端口
        • 2.1.1.3. URL路径中优先体现服务和资源
        • 2.1.1.4. URL路径命名规范
        • 2.1.1.5.  版本号
        • 2.1.1.6.  数据变量
        • 2.1.1.7.  避免传递无关参数
        • 2.1.1.8.  URL最大长度限制为2083字节
        • 2.1.1.9.  规定字段必须按照规范命名
      • 2.1.2.  请求方法 Request Method
      • 2.1.3.  状态码 Status Code
    • 2.2. 响应首部 Response Headers 
    • 2.3. 请求首部 Request Headers 
    • 2.4. 传参 Query / Body (form data) 
  • 3. 响应 Response
    • 3.1.【强制】响应数据格式规范                                                                     
  • 4. 其他规范 Other
    • 4.1.【强制】HTTP HEADER命名规范
    • 4.2. 传输规范
      • 4.2.1.【强制】传输协议规范
      • 4.2.2. 【强制】HTTP GZIP压缩传输规范说明
    • 4.3. 接口安全相关规范
      • 4.3.1.【强制】签名规范
      • 4.3.2.【强制】敏感数据加密规范
      • 4.3.3.【强制】登录接口特殊要求
      • 4.4.4. 【强制】接口相关的Cookie使用规范
  • 参考文档

 

 

需要确认的问题列表:

序号
是否完成
问题说明
解决方案
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_CNHTTP API Design

2.1.1.4.1.【强制】路径名称只能包含小写英文字母、数字和短划线,且第一个字符必须是小写英文字母,单词之间用短划线分隔;

正确示例:

/api/user-center/customers/43

错误示例:

/api/user_center/customers/43/get_token 应该是短划线 
/api/usercenter/customers/43/get_token 单词之间分隔
/api/userCenter/customers/43/get_token 不应该用小驼峰 

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/

{
    name: "张三",
    age: 18
}

JSON格式字符串作为HTTP BODY上送

(文件上传接口除外)


推荐PUT (CREATE或UPDATE) 新建或更新资源,如果存在,就更新,如果不存在,就新建。客户端可提供有变更的字段,但必须有唯一性标识,可以在路径中表示。

以下是添加或创建一个客户,路径特殊之处在于,带了id

/api/user-center/customers/448207

{
    name: "张三",
    age: 39
}
推荐PATCH(UPDATE) 在服务器更新资源(客户端提供改变的属性)

客户端上传部分字段数据,可以理解为对数据打个小补丁。特殊之处在于,字段只包含变更了的,没变更的字段不包含进JSON数据中。

/api/user-center/customers/448207

{
    name: "张三"
}

以下内容是对上表的详细说明:

  1. 五个方法,两个强制,三个推荐
  2. 【强制】GET和DELETE请求数据使用查询参数(query) 传
  3. 【强制】POST/PUT/PATCH请求数据采用JSON格式字符串作为HTTP BODY提交,文件上传接口除外
  4. 【推荐】文件上传接口允许使用表单提交(application/x-www-form-urlencoded或者multipart/form-data),UTF-8编码格式,可以增加一个MD5校验值参数,MD5校验无需盐值。
  5. 【推荐】需要支持探活的接口,实现时必须支持Method为HEAD的请求
  6. 【强制】请求HTTP HEADER中用"Content-Type"指明请求数据格式,使用"Accept"指明期望返回的数据格式,

             示例1(请求数据格式和期待响应数据格式都是JSON):

Content-Type: application/json;charset=UTF-8
Accept: application/json;charset=UTF-8

             示例2(请求数据格式表单,期待响应数据格式为JSON):

Content-Type: application/x-www-form-urlencoded;charset=utf-8
Accept: application/json;charset=UTF-8

       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

最详细的http协议、tcp/ip协议

理解RESTful架构

RESTful API 设计指南

dental - 编码规范

swagger官网

https://docs.microsoft.com/en-us/azure/architecture/best-practices/api-design

posted @ 2021-12-21 15:37  优前程  阅读(1489)  评论(0编辑  收藏  举报