什么是 REST

REST 一词,是由 HTTP 协议的主要设计者 Roy Fielding 在他 2000 年的博士论文中提出的。

论文地址:https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm

在这篇论文中,Roy Fielding 阐述了一种 Web 软件的架构风格(Architectural Style),并将其命名为 REST,即 Representational State Transfer(表征性状态转移) 的缩写。

论文中描述了 REST 的六大软件工程原则,符合这些原则的架构被称为 RESTful 架构。

  1. C/S架构。

  2. 无状态:服务端不记录客户端的状态,客户端的每次请求中都必须包含充分的信息,以便于服务端能够识别客户端的状态。

  3. 统一的接口

    1. 以资源为基础,使用 URI 来标识资源,请求的目标对象皆为资源,每个资源都可以通过 URI 访问到。
    2. 通过资源的表现层来操作资源。资源的表现层即资源的某种表示形式,比如数据库中的一条记录, 它的表现层可以是一段 JSON 数据,也可以是一段 HTML 数据,资源的表现层并不代表资源本身。当客户端请求 GET 一个资源时,服务端会将该资源的表现层返回给客户端。
  4. 可缓存:客户端允许缓存服务端响应的内容。

  5. 系统分层:在终端服务器与客户端之间允许存在中间层(如代理服务器)。

  6. 按需编码(可选):服务端可以通过给客户端返回一段功能代码(如 Javascript 代码)让客户端来执行,从而实现某些特定的功能。

作为 HTTP 协议的主要设计者,Roy Fielding 提出的 REST 架构风格恰恰是对 HTTP 协议的提倡与使用指导。HTTP 协议本身是一种面向资源的应用层协议,但是开发者们对 HTTP 的使用方式并不统一,很多 Web 服务的开发者们都并没有完全把 HTTP 当作应用层协议,而只是把它当做传输层协议来用,然后在 HTTP 之上又建立起了自己的应用层协议。这是 Roy Fielding 不希望看到的。

他倡导开发者们充分利用 HTTP 协议的特性(例如使用 HTTP Method 来指定对目标资源的操作)、遵从 HTTP 设计思想来开发 Web 服务。

从某种意义上来说,REST 架构风格就是遵从了 HTTP 设计思想的 Web 架构风格。

什么是 RESTful

RESTful 是 “REST” 的形容词形式,即“符合 REST 架构风格的”。符合 REST 架构风格的架构称为 RESTful 架构;符合 REST 架构风格的 Web 服务称为 RESTful Web 服务;符合 REST 架构风格的 Web API 称为 RESTful API。

Richardson 成熟度模型

Python 爬虫库 BeautifulSoup 的作者 Leonard Richardson 提出了一个成熟度模型,该模型把 RESTful Web 服务按照成熟度划分成 4 个层次:

  1. 第一个层次(Level 0)的 Web 服务只是使用了 HTTP 作为传输方式,不能算是 RESTful 服务。
  2. 第二个层次(Level 1)的 Web 服务引入了资源的概念,使用 URI 来标识资源。
  3. 第三个层次(Level 2)的 Web 服务使用不同的 HTTP 方法来进行不同的操作,并且使用 HTTP 状态码来表示不同的操作结果。
  4. 第四个层次(Level 3)的 Web 服务使用 HATEOAS(超媒体作为应用程序状态的引擎),HATEOAS 意味着资源的表现层为超媒体,超媒体是指包含指向其他资源链接的媒体,例如包含链接字段的 JSON 文本等。当客户端访问某个资源时,服务端给客户端返回的数据中,除了包含目标资源自身的数据之外,还包含与之相关的其他资源的链接,客户端可以根据这些链接来发现其他资源

RESTful API 设计最佳实践

  • URI 中尽量使用名词,原则上不使用动词,即 URI 仅用作对资源的标识。

  • 通过 HTTP Method 来指定对资源的操作。如 GET 表示获取资源、POST 表示新建资源、PUT 表示全局更新资源(需要在请求体中包含完整的目标资源的表现层,因而不推荐使用),PATCH 表示局部更新资源,DELETE 表示删除资源。

  • URI 中的名词一般采用复数形式,表示某类资源的集合,如 /tickets 表示全部 ticket 的集合。

  • 如果要表示集合中的单个资源,就在后面拼接这个资源的ID。如 /tickets/12,表示 ID 为12的那个 ticket。

  • 使用QueryString筛选集合中的元素,如 /tickets?status=1&sum>=100 ,表示状态为1且金额>=100的 ticket 的集合。

  • 通过 URI 的层层递进来建立资源的父子关系,如 /tickets/12/collections/3,表示 ID 为12的那个 ticket 下的 ID 为3的 collection。

  • 使用形容词来定制对某类资源的查询结果,如 /tickets/recently_closed 表示最近关闭的 ticket 的集合,/tickets/a_specialized 表示专门给a定制的 ticket 的集合。

  • 为了支持复杂查询,建议提供 /queries ,当客户端需要传递的参数过多时,允许客户端 POST /queries ,将查询参数放在请求体中传递过去, /queries 服务负责将请求体映射成一个 query 实体并写入数据库,然后返回 query_id。客户端拿到 query_id 后再 GET /tickets?query_id=111

  • 关于分页,HTTP 推荐将分页信息放在 Link 响应头中,参考 GitHub API 的设计,如下:

    Link: <https://api.github.com/user/repos?page=3&per_page=100>; rel="next",<https://api.github.com/user/repos?page=2&per_page=100>; rel="pre",<https://api.github.com/user/repos?page=1&per_page=100>; rel="first",<https://api.github.com/user/repos?page=50&per_page=100>; rel="last",

补充:HTTP 状态码及说明

  • 101 Switching Protocols:表示需要切换网络协议,此时客户端应当断开 HTTP 连接,使用指定的协议重新与服务端建立连接。

  • 200 OK:表示一切正常。

  • 201 Created :表示资源已成功创建,新资源的 URL 位于 Location 响应头中,用户可以选择在需要的时候访问它。

  • 301 Moved Permanently:表示目标资源被永久转移,新的 URL 位于 Location 响应头中,此时客户端应当对新的 URL 发起请求。

  • 302 Found:表示目标资源被临时转移,新的 URL 位于 Location 响应头中,此时客户端应当对新的 URL 发起请求。

  • 303 See Other:表示请求已被处理,但未返回处理结果,此时客户端应当请求另一个资源来获取处理结果,该资源的 URL 位于 Location 响应头中。

  • 307 Temporary Redirect:表示请求尚未被处理,是因为请求的资源不在本地,而在另一个 URL 处,客户端应当对那个 URL 发起请求,该 URL 位于 Location 响应头中。

    307 与 303 的区别:对于 GET 请求来说,307 与 303 没有区别,对于 POST、PUT、DELETE 请求来说,它们的区别在于,307 说明请求的操作尚未执行,而 303 说明请求的操作已经执行过了。

  • 400 Bad Request:表示用户发起的请求有问题,服务端无法处理该请求。

  • 401 Unauthorized:表示用户对该资源的访问尚未得到授权。

  • 403 Forbidden:表示用户无权访问该资源。

  • 404 Not Found:表示目标资源不存在。

  • 415 Unsupported Media Type:表示请求体的媒体类型与服务端所期望的不符。

  • 429 Too Many Requests:表示用户请求的次数过多,超出了服务端的限速阈值。

  • 500 Internal Server Error:表示服务端内部出现异常。

  • 502 Bad Gateway:表示客户端代理方面出现异常。

  • 503 Service Unavailable:表示服务端因繁忙或故障而拒绝本次服务,并通过响应头Retry-After告知客户端何时可以重试。

理解RESTful:理论与最佳实践的更多相关文章

  1. RESTful API 设计指南,RESTful API 设计最佳实践

    RESTful API 设计指南,RESTful API 设计最佳实践 网络应用程序,分为前端和后端两个部分.当前的发展趋势,就是前端设备层出不穷(手机.平板.桌面电脑.其他专用设备......). ...

  2. RHCS集群理论暨最佳实践

    RHCS集群理论暨 最佳实践 什么是集群?     集群是一组(>2)相互独立的,通过高速网络互联的计算机组成的集合.群集一般可以分为科学集群,负载均衡集群,高可用性集群三大类.     科学集 ...

  3. [转载]理解 Git 分支管理最佳实践

    原文 理解 Git 分支管理最佳实践 Git 分支有哪些 在进行分支管理讲解之前,我们先来对分支进行一个简单的分类,并明确每一类分支的用途. 分支分类 根据生命周期区分 主分支:master,deve ...

  4. RESTful API 设计最佳实践

    背景 目前互联网上充斥着大量的关于RESTful API(为了方便,以后API和RESTful API 一个意思)如何设计的文章,然而却没有一个"万能"的设计标准:如何鉴权?API ...

  5. ****RESTful API 设计最佳实践(APP后端API设计参考典范)

    http://blog.jobbole.com/41233/ 背景 目前互联网上充斥着大量的关于RESTful API(为方便,下文中“RESTful API ”简写为“API”)如何设计的文章,然而 ...

  6. RESTful API 设计最佳实践(转)

    摘要:目前互联网上充斥着大量的关于RESTful API(为了方便,以后API和RESTful API 一个意思)如何设计的文章,然而却没有一个”万能“的设计标准:如何鉴权?API格式如何?你的API ...

  7. RESTful API 设计最佳实践(转)

    背景 目前互联网上充斥着大量的关于RESTful API(为方便,下文中“RESTful API ”简写为“API”)如何设计的文章,然而却没有一个”万能“的设计标准:如何鉴权?API 格式如何?你的 ...

  8. RESTful API 设计最佳实践【转】

    背景 目前互联网上充斥着大量的关于RESTful API(为了方便,后面API和RESTful API 一个意思)如何设计的文章,然而却没有一个“万能”的设计标准:如何鉴权?API格式如何?你的API ...

  9. (转)RESTful API 设计最佳实践

    原文:http://www.oschina.net/translate/best-practices-for-a-pragmatic-restful-api 数据模型已经稳定,接下来你可能需要为web ...

随机推荐

  1. 渲染更换头像 文件转成url地址

                        需求:在一个后台页面中,插入iform页面,需求为更换头像(layui框架) 一.前提:创建user_buddha.html 页面 在侧边栏对应的 a 标签设置 ...

  2. 华为SEO搜索引擎主管招聘内容

    http://www.wocaoseo.com/thread-166-1-1.html 华为SEO搜索引擎主管招聘内容: 职位职责 1. 提出全站的SEO策略和实施计划,推动和监督计划实施:负责提升各 ...

  3. C# 接口的Get、Post、WebService请求方法一览,值得收藏

    C# 接口的Get.Post.WebService请求方法一览,值得收藏 public static class HttpHelper { const string DEFAULT_USER_AGEN ...

  4. 分享几个好用的ui框架,以便开发

    1:Layui--经典模块化前端框架 地址:https://www.layui.com/ 2:iview--基于 Vue.js 的高质量 UI 组件库 地址:http://v1.iviewui.com ...

  5. Python错误,pip安装包或更新时因超时而报错误

    报错原因 想要使用pip,结果出下以下警告: 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很多已经做案例的人,却不知道如何去学习更加高 ...

  6. 为什么golang中不存在三元运算符

    三元运算符广泛存在于其他语言中,比如: python: val = trueValue if expr else falseValue javascript: const val = expr ? t ...

  7. LuaBridge相关

    http://www.cppblog.com/sunicdavy/archive/2013/12/07/204648.html https://segmentfault.com/a/119000000 ...

  8. cometoj(A-D+F+H)代码

    A #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> ...

  9. SICP 习题1.10

    题目要求 解题方法 递归计算 没什么好说的,单纯的套用数学公示 (define (f n) (if (< n 3) n (+ (f (- n 1)) (* 2 (f (- n 2))) (* 3 ...

  10. Vue中父组件使用子组件的emit事件,获取emit事件传出的值并添加父组件额外的参数进行操作

    需求是这样的,需要输入这样一个列表的数据,可以手动添加行,每一行中客户编号跟客户姓名是自动关联的,就是说选取了客户姓名之后,客户编号是自动填充的,客户姓名是一个独立的组件,每一个下拉项都是一个大的对象 ...