一、Verbs(动词)
- GET (选择):从服务器上获取一个具体的资源或者一个资源列表。
- POST (创建): 在服务器上创建一个新的资源。
- PUT (更新):以整体的方式更新服务器上的一个资源。
- PATCH (更新):只更新服务器上一个资源的一个属性。
- DELETE (删除):删除服务器上的一个资源。
- HEAD : 获取一个资源的元数据,如数据的哈希值或最后的更新时间。【不常用】
- OPTIONS:获取客户端能对资源做什么操作的信息。
注意:1、GET请求可以被浏览器缓存(通常也是这样的);
2、HEAD请求是基于一个无响应体的GET请求,并且也可以被缓存的。
二、Versioning(版本控制)
一般来说有5种版本控制方式:
- Versioning
- 通过QueryString进行版本控制
- 通过URL PATH进行版本控制
- 通过Media Type进行版本控制
- 通过自定义Headers进行版本控制
三、Analytics(分析)
API分析就是持续跟踪那些正为人使用的API的版本和端点信息,第三方开发者通常会关注API的构建目的,其中最重要的一个目的是你决定什么时候不再支持某个版本。你需要明确的告知开发者他们正在使用那些即将被移除的API特性。这是一个很好的方式在你准备
删除旧的API之前去提醒他们进行升级。当然第三方开发者的通知流程可以以某种条件被自动触发,例如每当一个过时的特性上发生10000次请求时就发邮件通知开发者。
四、API Root URL
API的根地址很重要,API根入口点保持尽可能的简单是很重要的。比如:
- https://example.org/api/v1/* 顶级域名
- https://api.example.com/v1/* 二级域名
区别使用:
应用很庞大或者你预期它将会变的很庞大,那么将API放到子域下通常是一个好选择。这种做法可以保持某些规模化上的灵活性。
如果API不会变的很庞大,或是你只是想让应用安装更简单些(如你想用相同的框架来支持站点和API),将你的API放到根域名下也是可以的。
五、Endpoints (端点)
一个端点就是指向特定资源或资源集合的URL。
- https://api.example.com/v1/zoos
通过不同的动词来表达具体的业务需求:
- GET /zoos: List all Zoos (ID and Name, not too much detail)
- POST /zoos: Create a new Zoo
- GET /zoos/ZID: Retrieve an entire Zoo object
- PUT /zoos/ZID: Update a Zoo (entire object)
- PATCH /zoos/ZID: Update a Zoo (partial object)
- DELETE /zoos/ZID: Delete a Zoo
- GET /zoos/ZID/animals: Retrieve a listing of Animals (ID and Name).
- GET /animals: List all Animals (ID and Name).
- POST /animals: Create a new Animal
- GET /animals/AID: Retrieve an Animal object
- PUT /animals/AID: Update an Animal (entire object)
- PATCH /animals/AID: Update an Animal (partial object)
- GET /animal_types: Retrieve a listing (ID and Name) of all Animal Types
- GET /animal_types/ATID: Retrieve an entire Animal Type object
- GET /employees: Retrieve an entire list of Employees
- GET /employees/EID: Retreive a specific Employee
- GET /zoos/ZID/employees: Retrieve a listing of Employees (ID and Name) who work at this Zoo
- POST /employees: Create a new Employee
- POST /zoos/ZID/employees: Hire an Employee at a specific Zoo
- DELETE /zoos/ZID/employees/EID: Fire an Employee from a specific Zoo
比如:GET http://api.example.com/v1/animal_type/ATID,注:个人觉得,虽然这很规范,但是我们常用的api接口名并没有这么死板,非要用名词和固定的几个动词结合,看具体情况而定。
六、Filtering (过滤器)
可以添加一些过滤条件,例如:
- ?limit=10: 减少返回给客户端的结果数量(用于分页)
七、Status Codes (状态码)
比如后台返回值为200等,都需要规范。
公约规范如下:
1xx范围的状态码是保留给底层HTTP功能使用的,并且估计在你的职业生涯里面也用不着手动发送这样一个状态码出来。
2xx范围的状态码是保留给成功消息使用的,你尽可能的确保服务器总发送这些状态码给用户。
3xx范围的状态码是保留给重定向用的。大多数的API不会太常使用这类状态码,但是在新的超媒体样式的API中会使用更多一些。
4xx范围的状态码是保留给客户端错误用的。例如,客户端提供了一些错误的数据或请求了不存在的内容。这些请求应该是幂等的,不会改变任何服务器的状态。
5xx范围的状态码是保留给服务器端错误用的。这些错误常常是从底层的函数抛出来的,并且开发人员也通常没法处理。发送这类状态码的目的是确保客户端能得到一些响应。收到5xx响应后,客户端没办法知道服务器端的状态,所以这类状态码是要尽可能的避免。
八、Expected Return Documents (预期的返回文档)
当使用不同的HTTP动词向服务器请求时,客户端需要在返回结果里面拿到一系列的信息。下面的列表是非常经典的RESTful API定义:
- GET /collection: 返回一系列资源对象
- GET /collection/resource: 返回单独的资源对象
- POST /collection: 返回新创建的资源对象
- PUT /collection/resource: 返回完整的资源对象
- PATCH /collection/resource: 返回完整的资源对象
- DELETE /collection/resource: 返回一个空文档
九、Authentication
OAuth2.0提供了一个非常好的方法去做这件事。在每一个请求里,你可以明确知道哪个客户端创建了请求,哪个用户提交了请求,并且提供了一种标准的访问过期机制或允许用户从客户端注销,所有这些都不需要第三方的客户端知道用户的登陆认证信息。
还有OAuth1.0和xAuth同样适用这样的场景。无论你选择哪个方法,请确保它为多种不同语言/平台上的库提供了一些通用的并且设计良好文档,因为你的用户可能会使用这些语言和平台来编写客户端。
十、Content Type (内容类型)
只要你返回给他们有效的数据格式,开发者就可以使用流行的语言和框架进行解析。如果你正在构建一个通用的响应对象,通过使用一个不同的序列化器,你也可以很容易的提供之前所提到的那些数据格式(不包括SOAP)。而你所要做的就是把使用方式放在响应数据的接收头里面。
有些API的创建者会推荐把.json, .xml, .html等文件的扩展名放在URL里面来指示返回内容类型,但我个人并不习惯这么做。我依然喜欢通过接收头来指示返回内容类型(这也是HTTP标准的一部分),并且我觉得这么做也比较适当一些。
十一、Hypermedia APIs (超媒体API)
超媒体API概念的运作跟人们的行为类似。通过请求API的根来获得一个URL的列表,这个列表里面的每一个URL都指向一个集合,并且提供了客户端可以理解的信息来描述每一个集合。是否为每一个资源提供ID并不重要(或者不是必须的),只要提供URL即可。
十二、Documentation (文档)
老实说,即使你不能百分之百的遵循指南中的条款,你的API也不是那么糟糕。但是,如果你不为API准备文档的话,没有人会知道怎么使用它,那它真的会成为一个糟糕的API。
- 让你的文档对那些未经认证的开发者也可用
- 不要使用文档自动化生成器,即便你用了,你也要保证自己审阅过并让它具有更好的版式。
- 不要截断示例中请求与响应的内容,要展示完整的东西。并在文档中使用高亮语法。
- 文档化每一个端点所预期的响应代码和可能的错误消息,和在什么情况下会产生这些的错误消息
如果你有富余的时间,那就创建一个控制台来让开发者可以立即体验一下API的功能。创建一个控制台并没有想象中那么难,并且开发者们(内部或者第三方)也会因此而拥戴你。
另外确保你的文档能够被打印。CSS是个强大的工具可以帮助到你。而且在打印的时候也不用太担心边侧栏的问题。即便没有人会打印到纸上,你也会惊奇的发现很多开发者愿意转化成PDF格式进行离线阅读。
十三、Errata: Raw HTTP Packet (原始的http封包)
因为我们所做的都是基于HTTP协议,所以我将展示给你一个解析了的HTTP封包。我经常很惊讶的发现有多少人不知道这些东西。当客户端发送一个请求道服务器时,他们会提供一个键值对集,先是一个头,紧跟着是两个回车换行符,然后才是请求体。所有这些都是在一个封包里被发送。
服务器响应也是同样的键值对集,带两个回车换行符,然后是响应体。HTTP就是一个请求/响应协议;它不支持“推送”模式(服务器直接发送数据给客户端),除非你采用其他协议,如Websockets。
当你设计API时,你应该能够使用工具去查看原始的HTTP封包。