REST是一种架构风格,由Roy Thomas Fielding在他2000年的博士论文中提出,由于其简洁高效的设计,越来越多的网络服务开始采用REST风格设计和实现;本文主要根据业界已经总结出来的RESTful API的设计原则,并结合我工作中的API设计经验,总结出一套我认为最合适的设计准则
API(应用编程接口)大家都很熟悉,一套API的设计一般遵循以下步骤:
- 接口应用场景是什么
- 如何定义接口
- 其它注意点
对于接口应用场景我想不需要做过多阐述,既然是REST,基本就是网络应用场景了,本文将就后面两步进行详细阐述
1. 如何定义接口
-
Root URL尽量简洁
简洁总是好的,不要将API的Root URL设计得过于复杂,这样既没有必要,同时也会难以维护,API一般应该作为一个单独的服务向外提供,复杂的Root URL可能意味着你的系统拓扑有问题,所以尽量以简单明了的形式呈现Root URL:https://example.org/api/ https://api.example.com/
-
API上需标明版本
如果你能预见该API后期不会有迭代增长(基本不可能),那么可以不需要版本信息;否则带上版本信息,它能让后续扩展更加容易,同时也能保持前向兼容,版本信息也以简洁为主,如:https://example.org/api/v1/* https://api.example.com/v1/*
也有人建议将版本放置于header中,我个人认为放在header中没有放在API URL根部好
-
资源的操作采用名词形式
每个资源使用两个URL,资源集合用一个URL,具体某个资源用一个URL,如:/employees #资源集合的URL /employees/56 #具体某个资源的URL
-
非资源操作使用动词
有时API调用并不涉及资源(如计算,翻译或转换)。例:GET /translate?from=de_DE&to=en_US&text=Hallo
在这种情况下,API不会返回任何资源数据。而是执行一个操作并将结果返回给客户端。因此,你应该在URL中使用动词而不是名词,来清楚的区分资源请求和非资源请求
-
表述资源的名词采用复数形式
名词采用复数形式更多的是一种个人爱好,但复数形式在大部分情况下确实更加合理,如果一定要使用单数形式也可以,但需要注意的是不要同一个资源单复数混用,如:/animals # 复数 /animal/36 # 单数
这样看起来很混乱,且容易出错
-
使用HTTP action表达资源操作,而不要通过 动词+资源名词 表达
什么意思呢?比如下面的API示例:/getAllEmployees /getAllExternalEmployees /createEmployee /updateEmployee
它将对资源的操作表达成一个动词+资源名词形式的短语,这种形式的主要缺点在于API看起来比较凌乱,且每个资源对应的URL数目会较多,对比看更好的设计:
GET /employees GET /employees?state=external POST /employees PUT /employees/56
每个资源对应一个URL,通过HTTP action和HTTP参数来表述对资源的操作,形式统一,URL精简;具体 HTTP action与操作对应关系见下表:
URL POST(创建) GET(读取) PUT(提供整体信息) PATCH (提供局部信息) DELETE(删除) /employees 创建一个新员工 列出所有员工 批量更新员工信息 批量更新员工信息 删除所有员工 /employees/56 error 获取56号员工的信息 更新56号员工的信息 更新56号员工的信息 删除56号员工 另外还有两种并不常用的HTTP action
HEAD OPTIONS 返回资源的元数据,如资源的hash值,资源的更新时间等 返回允许客户端对该资源进行哪些操作 -
使用HTTP 响应状态码对结果进行分类
作为HTTP应用,使用HTTP响应状态码对结果进行分类不但符合通用的标准,还会带来很多其他好处,如一些负载均衡服务器就会自动减少对某些过多50X错误的服务器发送调用请求,常用的响应状态码有:2xx:成功 3xx:重定向 4xx:客户端错误 5xx:服务器错误 200 成功 301 永久重定向 400 错误请求 500 内部服务器错误 201 创建 304 资源未修改 401未授权 。。。 。。。 。。。 403 禁止 。。。 。。。 。。。 404 未找到 。。。 -
返回有用的错误提示
除了合适的响应状态码之外,还应该在HTTP响应正文中提供有用的错误提示和详细的描述。让调用方更方便的定位问题,如请求:GET /employees?state=super
对应响应:
// 400 Bad Request { "message": "您的请求参数status不符合要求,它必须是正整数", ... }
-
其他参数采用查询参数形式(
api?param=xxx
)而非路径参数形式(api/xxx
)
所谓其他参数指的是指不在REST规则里的参数,如过滤,搜寻,分页等,请求实例:/employees?offset=30&limit=15
-
根据使用场景决定返回格式类型
返回格式分为两种:- 数据格式,如json,xml等;当前大部分情况下都使用json,若非特殊考虑也是推荐使用json,它相较于xml更易读,且数据量更小
- 命名格式,如小驼峰命名法(
returnData
),下划线命名法(return_data
)等;命名格式一般需要根据客户端进行决定,比如调用的客户端基本都是WEB前端,那么使用小驼峰命名法会更好,以与JS兼容
其它注意点
-
安全第一
任何一个API,即便是内部API依然要考虑安全校验,如调用者身份验证,请求数据量是否超过阈值等 -
API文档很重要
实际中的API很少会100%遵循本文的原则,这样的API照样可以正常工作,但是如果你的API没有一份清晰易懂且及时更新的文档,那么对于大部分调用者来说,这就是烂API,好的文档能让调用者清楚的知道API的作用,同时为API提供者省去很多不必要的维护工作 -
跟踪所有API的调用情况,对使用频繁的API进行重点优化
这一点没有那么绝对,对于内部API接口,可以不需要;但是对于开放API接口,如果能针对调用频繁的API进行单独优化,那么就可以提升使用API体验 -
快过期的API也需要维护
对于快过期的API需要在文档提前声明,特定时间点哪些API将不再维护,同时返回404 not found或301重定向至当前可用的API
网友评论