Liao9144 / Blog

我的博客
1 stars 0 forks source link

RESTful API #1

Open Liao9144 opened 6 years ago

Liao9144 commented 6 years ago

什么是 RESTful

首先 REST 是 “Representational State Transfer” 的缩写,翻译为中文就是“表述性状态转移”,它是一种架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件,这套风格描述了网络资源是如何定义和寻址的。一个实现了 REST 这套风格(原则/约束)的服务就叫做 RESTful 的服务。

REST 风格(原则/约束)

如果还是不能理解上述所说的“什么是 RESTful”,那我把上述所说的合并成简洁的一句话:“URL 定位资源,用 HTTP 描述对资源操作和结果,以及资源的自我描述”。我们把这句话再详细的一一分解。

URL: API 与用户通信总是使用 HTTPS 协议; 尽量将 API 部署在专属域名下 https://api.example.com ,也可以放在主域名下 https://www.example.com/api ; 如有版本信息一般放在 url 中 https://api.example.com/v3,也可以放在头信息中,例如 https://api.github.com 的 v3 版本 REST API 时, Accept: application/vnd.github.v3+json

定位资源: 首先资源它是个东西,不是动作,所以用名词表示,而且资源往往与数据库的表对应,数据库中的表都是同种东西的集合,所以名词一般也是复数 https://api.example.com/v3/departments (资源名是否复数还是根据个人习惯吧); 另外命名应该可以体现资源的结构 https://api.example.com/v3/departments/{departmentId}/emoloyees ,这就表示了部门(department)和员工(employee)之前是主从关系,而 https://api.example.com/v3/department/{departmentId}/emoloyees/{employeeId} ,就表示了该部门下的某个员工; 如果记录数量很多,服务器不可能都将它们返回给用户,API 应该提供过滤参数,过滤返回结果,https://api.example.com/v3/departments?page=2&per_page=15

用 HTTP 描述对资源操作 对资源操作,用 HTTP 动词描述,HTTP 动词常见的有五个分别是: POST(创建资源)、 DELETE(删除资源)、 PUT(整体更新)、 PATCH(局部更新)、 GET(获取资源)。

用 HTTP 描述对资源操作的结果 服务器返回的数据格式,应该尽量使用JSON,避免使用XML; 针对不同操作,服务器向用户返回的结果应该符合规范:POST ---- 返回新生成的资源对象、DELETE ---- 返回一个空文档、PUT ---- 返回完整的资源对象、PATCH ---- 返回完整的资源对象、GET(s) ---- 返回资源对象的列表(数组)、GET ---- 返回单个资源对象; 要正确提供状态码,状态码是非常重要的,因为只有状态码会告诉 API 的使用者,请求是否如预期的成功或者失败,如果出现了错误,谁该为这个错误负责; 如果状态码是 4xx,就应该向用户返回出错信息。一般来说,返回的信息中将error作为键名,出错信息作为键值即可 { error: "Invalid API key" }

下面再列举一下 常见会用到的状态码: 200级别,表示成功:

400级别,表示客户端引起的错误:

500级别,服务器错误:

状态码的完全列表参见这里

资源的自我描述 资源的自我描述意思是资源可以告诉用户如何使用 API,如何与 API 交互,使得用户不查文档,也知道下一步应该做什么和能做什么。这种做法叫做 HATEOAS(Hypertext As The Engine Of Application State),中文翻译为“将超媒体格式作为应用状态的引擎”,核心思想就是每个资源都有它的状态,不同状态下,可对它进行的操作不一样。

POST https://api.example.com/v3/departments

{
    department : {
        id: 123456
    }
    "links" : [
        {
            "rel" : "self",
            "href" : "https://api.example.com/v3/departments/123456",
            "method" : "GET"
        }
        {
            "rel" : "emoloyees",
            "href" : "https://api.example.com/v3/departments/123456/emoloyees",
            "method" : "GET"
        }
        ....
    ] 
}

上面代码表示,文档中有一个 links 属性,用户读取这个属性就知道下一步应该做什么和能做什么了。每个 link 中 rel 表示这个 link 与当前资源的关系, href 表示 link 的 URL,method 表示这个 link 的 HTTP 动词。

其实上述描述的是 REST 风格(原则/约束)最重要的原则之一,统一接口。REST 有 6 大原则/约束:

  1. 客服端-服务端约束: 客户端和服务端是分离的,它们可以独自的进化;
  2. 无状态: 客户端和服务段的通信必须是无状态的,状态应包含在请求里的; 也就是说请求里要包含服务端需要的所有的信息,以便服务端可以理解请求并可以创造上下文;
  3. 分层系统: 就像其它的软件架构一样,REST也需要分层结构,但是不允许某层直接访问不相邻的层;
  4. 统一接口: 这里分为4点,它们是: 资源标识符(URI),资源的操作(也就是方法Method,HTTP动词), 自描述的响应(可以认为是媒体类型Media-Type),以及状态管理(超媒体作为应用状态的引擎 HATEOAS,Hypermedia as the Engine of Application State);
  5. 缓存:缓存约束派生于无状态约束,它要求从服务端返回的响应必须明确表明是可缓存的还是不可缓存的;
  6. 按需编码:这允许客户端可以从服务端访问特定的资源而无须知晓如何处理它们,服务端可以扩展或自定义客户端的功能。

Richardson 成熟度模型

image

Richardson 成熟度模型代表着你的API是否足够成熟,分为4个级别,0代表最差,3代表最好。

0级(Plain Old XML沼泽):这里HTTP协议只是被用来进行远程交互,协议的其余部分都用错了,都是RPC风格的实现(例如SOAP,尤其是使用WCF的时候); 1级(资源):这级里,每个资源都映射到一个URI上了,但是HTTP方法并没有正确的使用,结果的复杂度不算太高; 2级(动词):正确使用了HTTP动词,状态码也正确的使用了,同时也去掉了不必要的变种; 3级(超媒体):API支持超媒体作为应用状态的引擎 HATEOAS,Hypermedia as the Engine of Application State,引入了可发现性。

我觉得 Richardson 成熟度模型也可以用这句话描述:“URL 定位资源,用 HTTP 描述对资源操作和结果,以及资源的自我描述

只有满足了 6 个原则成熟度到 3 级系统才可以真正称得上是 RESTful 的,其实大部分系统的 RESTful API 并不是 RESTful 的,成熟度只做到 2 级(URL 定位资源,用 HTTP 描述对资源操作和结果) 但这样并不代表这些 API 就不好,REST 只是一种风格,不是规范,利弊需要开发人员去衡量。