通常情况下,在项目开发过程中涉及的API设计是采用REST API的模式,但并没有制定一个严格的、可理解的、可扩展的规范,从长远来看,随着项目的不断迭代,特别的在赶工期的情况下,REST API就会出现偏移。因此建议在项目初期就建立严格的API设计规范。
个人觉得好的API设计规范可能避免很多不必要的沟通,提高项目开发效率,接口本身就是文档。下面是我觉得REST API必须要遵守的9个设计规范。
1、使用HTTP方法赋予端点意义
REST API鼓励为应用程序的每个CRUD操作使用不同的HTTP方法。其中,有以下几种:GET
、POST
、PUT
、DELETE
和PATCH
。与资源相关联的端点的名称必须与应用的操作相关的HTTP方法对应。
// 不好的设计 GET /get_articles POST /insert_articles PUT /modify_articles DELETE /delete_articles //建议的设计 GET /articles POST /articles PUT /articles DELETE /articles
2、状态码须根据API的数据结果给出
应用程序最重要的特性之一是端点的返回与相应的状态码相关。这意味着,当我们的结果是成功还是失败的时候,可以用一种更描述性的方式来表达想要传达的数据。
例如,如果得到状态码200
,则可以立即知道API请求的结果是成功的,否则,如果得到状态码400
,结果是失败的。
重要的是要知道现有的状态码,并知道在什么情况下应用它们,因为返回消息可能与某些状态码错误地关联在一起(这是很常见的),这对于正常开发过程非常不友好,会给开发人员带来困惑。
// 不好的设计 { "status": 200, "error": {...} } // 建议的设计 { "status": 200, "data": [...] }
一些常见的HTTP状态码包括:
200
:成功的请求,通常是GET201
:创建后成功请求,通常是POST204
:成功的请求,没有返回任何内容,通常是PUT或PATCH301
:永久重定向到另一个端点400
:错误的请求(客户端应修改请求)401
:未经授权,凭据未被识别403
:禁止,凭据已接受但没有权限404
:找不到资源不存在410
:该资源先前已存在,但现在不存在429
:请求太多,用于速率限制,并且应包含重试标头500
:服务器错误,是通用的,值得一看的是其他500级错误503
:服务不可用,其中重试标头有用的另一个服务
3、过滤、排序和分页支持
在应用程序中,过滤、排序及分页是常见的,这样有助于用户查找到需要的信息,同样也能减少服务器资源的消耗(数据量大的情况下不分页可能会带来服务器资源的耗尽)。
GET /articles?title=api&cate_id=1
:过滤、检索所有具有以下属性的文章列表:标题为api,类型id为1。GET /articles?limit=10&offset=0
:分页,从0行开始返回10条。GET /articles?limit=10&offset=0&sort=asc&order=title
:排序,返回按名称升序排列的文章记录。
4、一致性端点设计
经常遇到的关于各种API开发的讨论之一就是如何设计端点?是使用单数还是复数。简而言之,我们希望在应用程序中保持API设计的一致性,为此,建议以复数形式来构建端点。
资源不会总是有一个结果,一个表可能会有许多结果,即使它只有一个结果,并且将其转为单数形式,我们也很难保持路由名称格式的一致性。
// 不好的设计 GET /article GET /article/:id // 建议的设计 GET /articles GET /articles/:id
5、用资源名称命名端点
谈到一致性,如果我们知道路由负责处理资源上的操作,那么有必要直接用资源的名称来命名端点,这样当开发人员使用API的时候,就知道API在处理哪些实体数据。
例如,需要增加订单,则不能/articles
作为端点,那就非常糟糕了。
6、资源层级设计
如果我们需要访问资源相关的实体数据怎么办呢?为了体现这种层级关系,有两个方式可以参考:
- 以端点分层设计
- 以参数设计
让我们以“作者”和“文章”的经典示例为例。
GET /authors/quintion/articles/rest-api-design GET /articles?author=quintion&title=rest-api-design
这些方法都是有效的,在很多平台上都已看到过它们。就个人而言,我认为使用查询字符串比扩展当前路径更简洁。应用程序扩展得越多,我们肯定会具有更大的层次结构,反过来,路由也会扩展。即使这样,它还是根据每个人的标准,使用最喜欢的一种。
7、版本控制
随着项目的迭代,不可避免的是要有一个稳定且明确的API版本,且没有错误和歧义。假设我们部署了API,并且有几个客户端开始使用它,那么当需要从资源中添加或删除更多数据时,会发生什么情况?可能会在使用我们接口的外部服务上产生错误。这就是为什么对我们的应用程序要有具有版本控制的原因。
有几种方法,但我是URI版本的支持者,在该版本中,我们将在端点中明确拥有路由的版本。
// URI 版本 v[x] GET /v1/news GET /v2/articles
8、缓存机制
高速缓存是一种可以提高API速度和降低资源消耗的强大工具之一,其原理就是对相同结果的请求,减少对数据库的操作。有多种方式可以帮助我们实现缓存系统,其中之一文件缓存,如 Redis。
当然实现缓存机制通常也会带来成本,原则就是需要问一下:信息是动态的还是静态的?如果是动态的,信息多久更改一次?
重要的是要知道缓存中有很长时间的信息,这可能会由于长时间保留信息而导致API的错误结果,建议缓存时间设计得短一点。
9、设计文档
文档是项目开发和协作最好的工具之一,也是很多研发人员最讨厌的。在这种情况下,文档化的API是必不可少的,以便使用我们API的用户可以理解我们界面的几个重要方面,包括可访问性、响应、请求、示例。
-
可访问性:界面的位置和交互是最重要的特征之一,我们不想给客户一个操作手册文档。将我们的文档公开在云上,让每个人都能看到,这是我们能做的最方便的事情
-
响应和请求:我们提供的信息必须考虑任何资源可能产生的所有可能结果以及如何使用它们。
-
示例:提供如何使用接口的示例非常重要,即使它是一个可以在控制台中执行并从中获得响应的bash脚本。
结论
请记住,我们设计的API水平如何能够暴露一个开发人员的资质,一个API的最佳设计,能够使项目中的所有人员都喜欢。当然一个最佳的REST API实践还有其他的原则,并且需要开发人员共同保持一致性。