本文本身不是规范,而是指引做规范的。
应认真考虑要不要使用RESTful规范,不要盲目跟风。它的缺点在小公司里特别明显:
如果确定使用,可以参考Github上这两个最多star的规范
无论是独立的wiki还是整合在网关系统中,文档系统都应该支持全局模糊搜索。
文档有3种,全局设计规范、API参考手册、文档系统本身的使用指南。
其中,参考手册的每个API说明应包括这些信息:
大小写和连接符的规范应该全局统一:snake_case或者camelCase。一般snake_case会更像普通的web URL。
如果使用RESTful,URL格式可以是
https://api.example.com/{service_name}/{version}/{api_name}?{filters}
或
https://www.example.com/api/{service_name}/{version}/{api_name}?{filters}
。
注:Web URL和API URL的规范是不同的。
如果不用RESTful,最好也不要把参数放到header里,尽量在HTTP协议框架内实现业务。在此前提下,如果存在(所有接口都需要的)公共参数,可以放在URL query里;或者最方便地使所有接口的method都是POST然后放body里。
JSON格式的Content-Type
是application/json
。如果进行了加密和BASE64转码,正确的Content-Type
应该是text/plain
。
如有必要,可进一步指定编码:application/json;charset=utf-8
。
(以下讨论的是放在body里的JSON。)
各个key的大小写和连接符的规范应该全局统一:snake_case或者camelCase。
必填参数应该约定默认值。如不指定,可认为各类型的默认值是0
、0.0
、{}
、[]
、""
、false
,决不能是null
或undefined
。
非必填参数在无值时有3种风格,应该选定一种全局统一:
null
undefined
非必填参数不允许是这个参数类型的默认值(0
、0.0
、{}
、[]
、""
、false
)
值是数字就用数字类型,不要用字符串。
布尔类型用JSON的语义true/false
来表示,不要用1/0
。
值为枚举时,尽量用字符串表示而不是用数字。牺牲一点点性能但可以大大增强代码可读性。这能大幅降幅维护成本,减少出错。
// 直接把枚举value写成字符串更便于开发维护
type: "duck",
type: "chicken"
// “用数字表示然后在文档中详细说明”可读性差,通常不会有人把文档复制成代码注释
type: 1, // duck
type: 2 // chicken
尽量不要为前端做格式化。例如时间,应返回“1970年1月1日0点至今的秒数”或者“按ISO8601进行格式化的UTC(世界标准时间)时间”,而不是直接返回“2018年11月11日 23:22:33”。让大前端自己做格式化能更好应对UI变化以及兼容特殊要求。比如客户端从中文切换成英文,界面上的“5月6日”需要变成“May 6th”;这种场景下如果是后端传的“5月6日”,那无论是再次请求英文还是客户端自行解释时间后做转换都是糟糕的设计。
保证向后兼容的前提下及时删除废弃的参数或接口。可以先对参数或接口标记Deprecated
,在前端发布后或客户端强制升级后删除。
同一意义的字段名,在不同接口返回的命名统一。不要这边叫“page_count”,那边叫“page_size”或"page_amount"。
较常见的JSON结构是这样的:
{
"status": 0,
"message": "",
"data": {}
}
其中,错误码和错误信息也可以设计一份全局统一的对照表。需要注意的是,这里的status都表示业务情况,跟HTTP的status不要混用。 各级网关都可能以HTTP status表示错误,故它无法明确表示是业务API的问题。简单的例子是,业务API鉴权失败,HTTP也应该返回200 OK而不是返回401。因为接口是正常的,是数据逻辑不正确。
如果不用考虑多语言,message
错误信息可以是面向用户的中文语句,由前端/客户端直接toast告知用户。
请求参数应包含:
响应参数应包含:
为了减少请求数,后端可提供组合请求接口,并且可组合任意接口。以下设计仅是举例:
假如有3个接口(示例的响应体经简化仅保留data
):
/a
:请求{"a": "a"}
会响应{"data": {"d": "d"}}
/b
:请求{"b": "b"}
会响应{"data": {"e": "e"}}
/c
:请求{"c": "c"}
会响应{"data": {"f": "f"}}
增加一个接口/combo
可以一次性获取这3个接口的数据:
// 请求
{
"api": {
"/a": {"a": "a"},
"/b": {"b": "b"},
"/c": {"c": "c"}
}
}
// 响应
{
"data": {
"/a": {"data": {"d": "d"}},
"/b": {"data": {"e": "e"}},
"/c": {"data": {"f": "f"}}
}
}
AES
、DES
、3DES
、RSA
、DSA
、ECC
等算法。一般会对密文做BASE64转码再在网络上传输。MD5
、SHA1
、HMAC
等算法。签名只能放在URL query或HTTP header中。timestamp
、nonce
等机制,在一定时间内重复即认为是重放。或者timestamp距今超过一定时间的,认为是非法请求。最好在测试环境能通过参数控制上述机制的开关,方便调试、测试。