RESTful API设计指南

RESTful API设计指南

RESTful API概述

RESTful API是什么

RESTful是Representational State Transfer的缩写,代表着表征状态转移。REST拥有一组架构约束条件和原则,只要符合这一套约束原则的架构,就是RESTful架构。
需要注意的是,REST并没有提供新的组件、技术,也并不是专门为HTTP提供规范,而是通过约束和原则去合理使用Web的现有特征和能力(是的,REST受到Web现有特征的影响还是比较深的)。RESTful API 是一种围绕 资源(resource) 展开的 无状态传输 的API设计方案。所有的HTTP Action,都应该是在相应resource上可以被操作和处理的,而API 就是对资源的管理操作,而这个具体操作是由 HTTP Action 指定的。
这里写图片描述
RESTful API在功能上更像是隔离层,要访问服务器资源,就必须找到API入口。如果这个入口的规则遵循REST风格,那就是RESTful设计框架。

RESTful API产生的意义

近年来随着移动互联网的发展,各种类型的Client层出不穷,RESTful可以通过一套统一的接口为 Web,iOS和Android提供服务。另外对于广大平台来说,比如Facebook platform,微博开放平台,微信公共平台等,它们不需要有显式的前端,只需要一套提供服务的接口,于是RESTful更是它们最好的选择。

规定的资源格式

资源的标识URI

资源的是一个数据单元,这个单元可大可小,根据业务规模自主定制。要准确识别一个资源,需要有一个唯一标识,在Web中这个唯一标识就是URI(Uniform Resource Identifier)。
URI的设计应该具有自释性,可寻址性,直观性的原则。用/来表示层级,用_或-来分割单词,用?来过滤资源。
比较常见的URI:

HTTP协议语义支持

  • GET:从服务器取出资源或资源列表
  • POST:在服务器新建一个资源
  • PUT:客户端提供数据,以整体的方式更新服务器资源
  • PATCH:只更新服务器一个资源的一个属性
  • DELETE:从服务器删除资源
  • HEAD:从服务器获取报头信息(不是资源)
  • OPTIONS:获取客户端能对资源做什么操作的信息

除了POST不是幂等的,其他几个都是幂等的。
HTTP的幂等性是指一次和多次请求某一个资源应该具有同样的副作用。幂等性的一个实例:在网速不够快的条件下,客户端发送第一个请求后不能立即得到响应,由于不能确定是否请求是否被成功提交,所以它有可能会再次发送另一个相同的请求,幂等性决定了第二个请求是否有效。幂等情况下,第一次请求成功实现了事务操作,第二次请求就一定不能再次操作事务。

媒体类型

客户端与服务端进行交互式,需要规定双方能够接受的媒体表现形式。常见的媒体格式类型有:

  • application/json:JSON数据格式
  • application/xhtml+xml:XHTML数据格式
  • application/xml:XML数据格式
  • application/atom+xml:ATOM XML聚合格式

在设计RESTful API的时候,要规定端端之间具有统一的数据传输格式,目前JSON数据格式使用范围比较广。

好的API是什么样的

大家都知道,API表达的是数据和数据使用者之间契约的说明。打破这样一种契约会造成客户端数据没办法正确获取,文档的效果也大打折扣。
那一个好的API是要应该做到可扩展的。随着业务和服务的开张,这样的API要成长为一个公共平台的契约说明。为了做到广义适配,需要有一定的规范,从而让广大的用户轻松地消费这个平台的数据。API也容易使用,第三方调用者在使用上更为方便,用户调用这个API来消费平台数据,这个平台的数据也更为有价值。

关于Version版本化

https://developer.github.com/v3/git/tags/
版本化信息可以放在URI中,也可以放在请求头里面(Github选择前一种方案)
无论你正在构建什么,无论你在入手前做了多少计划,你核心的应用总会发生变化,数据关系也会变化,资源上的属性也会被增加或删除。只要你的项目还活着,并且有大量的用户在用,这种情况总是会发生。
请谨记一点,API是服务器与客户端之间的一个公共契约。如果你对服务器上的API做了一个更改,并且这些更改无法向后兼容,那么你就打破了这个契约,客户端又会要求你重新支持它。为了避免这样的事情,你既要确保应用程序逐步的演变,又要让客户端满意。那么你必须在引入新版本API的同时保持旧版本API仍然可用。
注:如果你只是简单的增加一个新的特性到API上,如资源上的一个新属性或者增加一个新的端点,你不需要增加API的版本。因为这些并不会造成向后兼容性的问题,你只需要修改文档即可。
随着时间的推移,你可能声明不再支持某些旧版本的API。申明不支持一个特性并不意味着关闭或者破坏它。而是告诉客户端旧版本的API将在某个特定的时间被删除,并且建议他们使用新版本的API。
一个好的RESTful API会在URL中包含版本信息。另一种比较常见的方案是在请求头里面保持版本信息。但是跟很多不同的第三方开发者一起工作后,我可以很明确的告诉你,在请求头里面包含版本信息远没有放在URL里面来的容易。

根URL

https://developer.github.com/v3/git/tags/为例,其根URL是https://developer.github.com/v3/
这里可能大家会有疑惑,前面提到的是URI,后面怎么说的是URL,其实这里有一些包含与被包含的关系,用一张图来说明。
这里写图片描述

添加过滤

大数据包的传输过程中容易丢包,针对这种情况,可以让客户端自己对结果做一些具体的过滤或限制,这么做最重要的一个原因是可以最小化网络传输,并让客户端尽可能快的得到查询结果。其次是客户端可能比较懒,如果这时服务器能对结果做一些过滤或分页,对大家都是好事。另外一个不那么重要的原因是(从客户端角度来说),对服务器来说响应请求的负载越少越好。
所以只要出现GET的请求,就应该通过URL来过滤信息。以下有一些过滤器可以这么添加到API中的:

  • ?limit=10:减少返回给客户端的结果数量(用于分页)
  • ?offset=10:发送一堆信息给客户端(用于分页)
  • ?animal_type_id=1:使用条件匹配来过滤记录
  • ?sortby=name&order=asc:对结果按特定属性进行排序

状态码

HTTP状态码是RESTful API很重要的一部分。它是一个HTTP标准,很多的网络设备都可以识别这些状态码,例如负载均衡器可能会在发现某台web服务器已经发送了很多的50X服务器错误之后,避免可能会通过配置避免发送请求到这台服务器上。

1xx范围的状态码是保留给底层HTTP功能使用的,并且估计在你的职业生涯里面也用不着手动发送这样一个状态码出来。

2xx范围的状态码是保留给成功消息使用的,你尽可能的确保服务器总发送这些状态码给用户。

3xx范围的状态码是保留给重定向用的。大多数的API不会太常使用这类状态码,但是在新的超媒体样式的API中会使用更多一些。例如304是指资源未被改动,可以使用客户端缓存。

4xx范围的状态码是保留给客户端错误用的。例如,客户端提供了一些错误的数据或请求了不存在的内容。这些请求应该是幂等的,不会改变任何服务器的状态。属于 客户端错误

5xx范围的状态码是保留给服务器端错误用的。这些错误常常是从底层的函数抛出来的,并且开发人员也通常没法处理。发送这类状态码的目的是确保客户端能得到一些响应。收到5xx响应后,客户端没办法知道服务器端的状态,所以这类状态码是要尽可能的避免。属于 服务端错误

认证方式

OAuth2.0提供了一个请求的认证方式。在每一个请求里,可以明确知道哪个客户端创建了请求,哪个用户提交了请求,并且提供了一种标准的访问过期机制或允许用户从客户端注销,所有这些都不需要第三方的客户端知道用户的登陆认证信息。

还有OAuth1.0和xAuth同样适用这样的场景。无论你选择哪个方法,请确保它为多种不同语言/平台上的库提供了一些通用的并且设计良好文档,因为用户可能会使用这些语言和平台来编写客户端。

为API配上文档

API没有文档,对于第三方开发者来说简直是非常打击的一件事。文档应该遵循以下规则:

  1. 具有良好的版式。
  2. 请求和响应的内容应该有完整的东西,并在文档中使用高亮语法。
  3. 文档的每一个端点所预期的响应代码和可能的错误消息和错误消息的出现场景说明。
  4. 可能的话,创建控制台来让开发者立即体验API的功能。(非必要)
  5. 保证文档的输出格式能被打印。

RESTful API实践

Github的API是RESTful API的一种实践,可以当作参考来学习。
这里摘取了Github的几个uri:
https://github.com/pulls
https://github.com/settings/profile
https://github.com/username?tab=stars
https://developer.github.com/v3/git/tags/

URL

URL中应该尽量使用专属名词,避免使用动词。并将API部署在专用域名之下。

路径

路径又称为端点(endpoint),表示具体的地址。
在RESTful架构中,每个网址都代表一种资源,所以网址中不能有动词,只能有名词,所用的名词往往和数据库中的表格名对应。
比如github的pulls和settings的路径如下:
https://github.com/pulls
https://github.com/settings/profile

找到合适的媒体类型

当需要设计一个API时,可以去找特定领域内的特定设计,这样就不必要重复设计轮子了。
在数据返回格式方面,大部分的网站优先提供XML、JSON的数据返回,Google定义的GData就是在ATOM基础上作了扩展,还有一些网站提供了PHP的数据返回。

友好性

友好性主要表现在易扩展,后期需要的功能可以方便添加;
API也应该对上层UI友好,能够灵活支持,并可以适用于任何操作系统。
这里写图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章