REST 概念来源

  网络应用程序,分为前端和后端两个部分。当前的发展趋势,就是前端设备层出不穷(手机、平板、桌面电脑、其他专用设备...)。 因此,必须有一种统一的机制,方便不同的前端设备与后端进行通信。这导致 API 构架的流行,甚至出现"API First"的设计思想。

2000 年,Roy Thomas Fielding 博士在他那篇著名的博士论文 《Architectural Styles and the Design of Network-based Software Architectures》中提出了几种软件应用的架构风格。 REST 作为其中的一种架构风格在这篇论文的第5章中进行了概括性的介绍。

REST 是一种很笼统的概念,它代表一种架构风格。 对于多个 Web 应用采用的架构,我们只能说其中某一个比其它的更具有 REST 风格, 而不能简单粗暴地说:“它采用了 REST 架构而其它的没有”。 为了将 REST 真正地落地,Lenoard Rechardson & Sam Ruby 在《RESTful Web Services》一书中 提出了一种名为“面向资源的架构(ROA: Resource Oriented Architecture)”。 该书中介绍了一些采用 ROA 架构的 Web 服务应该具备的基本特征。

RESTful Web API 设计只是 REST 风格架构设计中的一个环节,并没有统一的标准。下面介绍的是一些比较没有争议的实践原则。

实践原则

1.版本化你的 API

  应该尽量将 API 部署在专用域名之下。

    https://api.example.com

  如果确定 API 很简单,不会有进一步扩展,可以考虑放在主域名下。

    https://example.org/api/

  应该将 API 的版本号放入 URL。

    https://api.example.com/v1/

  另一种做法是,将版本号放在 HTTP 头信息中,但不如放入 URL 方便和直观。Github 采用这种做法。

2.URI 使用名词和 ID 而不是动词

  在 RESTful 架构中,每个网址代表一种资源(resource),所以网址中不能有动词,只能有名词, 而且所用的名词往往与数据库的表格名对应。 一般来说,数据库中的表都是同种记录的"集合"(collection),所以 API 中的名词也应该使用复数。

举例来说,有一个 API 提供动物园(zoo)的信息,还包括各种动物和雇员的信息,则它的路径应该设计成下面这样。

    https://api.example.com/v1/zoos
https://api.example.com/v1/animals
https://api.example.com/v1/employees

3.使用 HTTP 协议标准动词改变状态

  使用 PUT, POST 和 DELETE 方法 而不是 GET 方法来改变状态。 对于资源的具体操作类型,由 HTTP 动词表示。

  常用的 HTTP 动词有下面五个(括号里是对应的 SQL 命令)。

    GET(SELECT):从服务器取出资源(一项或多项)。
POST(CREATE):在服务器新建一个资源。
PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。
PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。
DELETE(DELETE):从服务器删除资源。

  还有两个不常用的 HTTP 动词。

    HEAD:获取资源的元数据。
OPTIONS:获取信息,关于资源的哪些属性是客户端可以改变的。

  下面是一些例子。

    GET /zoos:列出所有动物园
POST /zoos:新建一个动物园
GET /zoos/ID:获取某个指定动物园的信息
PUT /zoos/ID:更新某个指定动物园的信息(提供该动物园的全部信息)
PATCH /zoos/ID:更新某个指定动物园的信息(提供该动物园的部分信息)
DELETE /zoos/ID:删除某个动物园
GET /zoos/ID/animals:列出某个指定动物园的所有动物
DELETE /zoos/ID/animals/ID:删除某个指定动物园的指定动物

4.过滤信息不涉及状态改变

  如果记录数量很多,服务器不可能都将它们返回给用户。API 应该提供参数,过滤返回结果。 常用的过滤包括分页、排序等等。 下面是一些常见的参数。

    ?limit=10:指定返回记录的数量
?offset=10:指定返回记录的开始位置。
?page=2&per_page=100:指定第几页,以及每页的记录数。
?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序。
?animal_type_id=1:指定筛选条件

  参数的设计允许存在冗余,即允许 API 路径和 URL 参数偶尔有重复。 比如,GET /zoo/ID/animals 与 GET /animals?zoo_id=ID 的含义是相同的。

5.使用 Http 头声明请求和响应的格式

  在客户端和服务端,双方都要知道通讯的格式,格式在 HTTP-Header 中指定

    Content-Type 定义请求格式,比如 URL 格式
Accept 定义系列可接受的响应格式,JSON,XML 等等

  这个并不强制,实践中也可以通过参数来指定返回内容的格式

6.优先使用 JSON 格式返回结果

  当设计 API 返回结果时,优先使用 JSON 格式,但不强制。 当请求的 URL 表明的是一个集合时,则返回结果为数组形式。 例如:

        {
"data":[
{
"login": "jerry1",
"id": 1,
"avatar_url": "https://...."
},
{
"login": "jerry2",
"id": 2,
"avatar_url": "https://...."
},
{
"login": "jerry3",
"id": 3,
"avatar_url": "https://....",
}
]
}

  当请求为单个对象时,则返回结果为 MAP 形式。例如,访问 https://api.test.com/users/test 时:

        {
"login": "jerry4",
"id": 1,
"avatar_url": "https://avatars.githubusercontent.com/u/1?v=3"
}

7.使用超媒体链接来组织文档

  Hypermedia as the Engine of Application State 超媒体作为应用状态的引擎,超文本链接可以建立更好的文本浏览体验。

  RESTful API 最好能做到 Hypermedia,即返回结果中提供链接,连向其他 API 方法,使得用户不查文档,也知道下一步应该做什么。

  比如,当用户向 api.example.com 的根目录发出请求,会得到这样一个文档。

        {
"link": {
"rel": "collection https://www.example.com/zoos",
"href": "https://api.example.com/zoos",
"title": "List of zoos",
"type": "application/vnd.yourformat+json"
}
}

  上面代码表示,文档中有一个 link 属性,用户读取这个属性就知道下一步该调用什么 API 了。 rel表示这个 API 与当前网址的关系(collection 关系,并给出该 collection 的网址), href 表示 API 的路径,title 表示 API 的标题,type 表示返回类型。

Hypermedia API 的设计被称为 HATEOAS。Github 的 API 就是这种设计,访问 api.github.com 会得到一个所有可用 API 的网址列表。

        {
"current_user_url": "https://api.github.com/user",
"authorizations_url": "https://api.github.com/authorizations",
// ...
}

从上面可以看到,如果想获取当前用户的信息,应该去访问 api.github.com/user,然后就得到了下面结果。

        {
"message": "Requires authentication",
"documentation_url": "https://developer.github.com/v3"
}

8.使用 Http 状态码处理错误

  如果你的 API 没有错误处理是很难的,只是返回 500 和出错堆栈不一定有用

  Http 状态码提供 70 个出错,我们只要使用 10 个左右:

    200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。
201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
204 NO CONTENT - [DELETE]:用户删除数据成功。
400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。
401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。
403 Forbidden - [*] 表示用户得到授权(与 401 错误相对),但是访问是被禁止的。
404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。
406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求 JSON 格式,但是只有 XML 格式)。
410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。
422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。
500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。

  使用详细的错误包装错误:

        {
"errors":[
{
"userMessage": "Sorry, the requested resource does not exist",
"internalMessage": "No car found in the database",
"code": 34,
"more info": "http://dev.mwaysolutions.com/blog/api/v1/errors/12345"
}
]
} just here , jerry

RESTful Web API 实践的更多相关文章

  1. 对RESTful Web API的理解与设计思路

    距离上一篇关于Web API的文章(如何实现RESTful Web API的身份验证)有好些时间了,在那篇文章中提到的方法是非常简单而有效的,我在实际的项目中就这么用了,代码经过一段时间的磨合,已经很 ...

  2. 我所理解的RESTful Web API [Web标准篇]

    REST不是一个标准,而是一种软件应用架构风格.基于SOAP的Web服务采用RPC架构,如果说RPC是一种面向操作的架构风格,而REST则是一种面向资源的架构风格.REST是目前业界更为推崇的构建新一 ...

  3. 我所理解的RESTful Web API [设计篇]

    <我所理解的RESTful Web API [Web标准篇]>Web服务已经成为了异质系统之间的互联与集成的主要手段,在过去一段不短的时间里,Web服务几乎清一水地采用SOAP来构建.构建 ...

  4. ASP.NET Web API实践系列04,通过Route等特性设置路由

    ASP.NET Web API路由,简单来说,就是把客户端请求映射到对应的Action上的过程.在"ASP.NET Web API实践系列03,路由模版, 路由惯例, 路由设置"一 ...

  5. About Restful Web Api Something.

    这种轻量级的服务架构目前来说还是比较流行的,比如微信的公众平台的接口开发就是一个很好的案例,提到restful那么他到底是一个什么样的东西? REST(Representational State T ...

  6. 【ASP.NET MVC 学习笔记】- 19 REST和RESTful Web API

    本文参考:http://www.cnblogs.com/willick/p/3441432.html 1.目前使用Web服务的三种主流的方式是:远程过程调用(RPC),面向服务架构(SOA)以及表征性 ...

  7. RESTful Web API 理解

    REST 是一种应用架构风格,不是一种标准,是面向资源架构(ROA)风格,与具体技术平台无关,REST架构的应用未必建立在Web之上,与之对应的是传统的Web Service 采用的面向操作的RPC架 ...

  8. ASP.NET Web API实践系列07,获取数据, 使用Ninject实现依赖倒置,使用Knockout实现页面元素和视图模型的双向绑定

    本篇接着上一篇"ASP.NET Web API实践系列06, 在ASP.NET MVC 4 基础上增加使用ASP.NET WEB API",尝试获取数据. 在Models文件夹下创 ...

  9. ASP.NET Web API实践系列05,消息处理管道

    ASP.NET Web API的消息处理管道可以理解为请求到达Controller之前.Controller返回响应之后的处理机制.之所以需要了解消息处理管道,是因为我们可以借助它来实现对请求和响应的 ...

随机推荐

  1. 使用spring注解——定义bean和自动注入

    对于java bean的定义和依赖配置,使用xml文件真心是不方便. 今天学习如何用注解,解决bean的定义和注入. 常用注解: 1.自动注入:@Resources,@Autowired 2.Bean ...

  2. Simple2D-23(重构)反走样几何图形

    以前 Simple2D 使用 Canvas2D 对象来绘制几何图形,而且渲染出来的几何图形存在明显的锯齿.如果想要抗锯齿的几何图形,则需要开启 OpenGL 的 MSAA,这需要很大的开销. 如果不使 ...

  3. Django模型的filed type总结

    1)AutoField:如果没有指明主键,就会产生一个自增的主键 2)BigIntegerField:64位的整形数值,从 -2^63 (-9223372036854775808) 到 2^63-1( ...

  4. eclipse 自动生成json格式的toString()方法

    文本代码 {"${member.name()}":"${member.value}", "${otherMembers}"}

  5. 基元线程同步构造之 Mutes(互斥体)

    互斥体实现了“互相排斥”(mutual exclusion)同步的简单形式(所以名为互斥体(mutex)). 互斥体禁止多个线程同时进入受保护的代码“临界区”(critical section). 因 ...

  6. 深入MySQL用户自定义变量

    一.到底MySQL的变量分哪几类? MySQL变量一共分为两大类:用户自定义变量和系统变量.如下: 用户自定义变量 局部变量 会话变量 系统变量 会话变量 全局变量 本文涉及的内容为用户自定义会话变量 ...

  7. Gviz

    1) Introduction 为了理解基因组数据,通常旨在在基因组浏览器中绘制这样的数据,以及各种基因组注释特征,例如基因或转录物模型,CpG岛,重复区域等.这些功能可以从ENSEMBL或UCSC等 ...

  8. rabbitmq web管理界面 用户管理

    安装最新版本的rabbitmq(3.3.1),并启用management plugin后,使用默认的账号guest登陆管理控制台,却提示登陆失败. 翻看官方的release文档后,得知由于账号gues ...

  9. UnicodeEncodeError: ‘ascii’ codec can’t encode

    [UnicodeEncodeError: ‘ascii’ codec can’t encode] Python默认环境编码通过下面的方法可以获取: 基本上是ascii编码方式,由此Python自然调用 ...

  10. JSP页面与JSP页面之间传输参数出现中文乱码的解决方案

    在学习编程初期JSP与JSP页面之间传输参数大多数都是使用这样的方式 index.jsp?id=*&name=* 这样的传输方式实质上是一种GET传输方式, 那如果出现了中文乱码, 解决方法其 ...