RESTful架构总结
RESTful架构
1:什么是互联网软件
在传统开发中,软件开发主要是单片机开发,而网络开发主要是系统之间的通信,软件开发和网络开发之间交集较少,但是互联网的兴起,使的软件开发和网络开发开始开始融合,因此,网站的开发也可以采用软件开发的模式,即“互联网软件”,采用客户端/服务端的模式,建立在分布式系统上,通过互联网通信,具有高并发,高延时的特征。
RESTful就是一种互联网软件架构。
2:什么是REST?
REST是表述性状态传递
英文名:Representational State Tansfer
是Roy Fielding博士在他的2000年的博士论文中提出来的
注:Roy Fielding是HTTP规范的主要编写者之一,Apache服务软件的作者之一,Apache基金会的第一任主席,在他的论文中写到:“我这篇文章的写作目的,就是想在符合架构原理的前提下,理解和评估以网络为基础的应用软件的架构设计,得到一个功能强、性能好、适宜通信的架构。REST指的是一组架构约束条件和原则。”
RESTful本身并没有提供新的技术和服务,它是基于HTTP、URI等web技术的标准和约束,原则上REST并不是HTTP唯一的,只是目前只有http实现了REST。REST是一种设计风格,不是规则。
表述性状态转移是一种架构约束条件和原则,主要是满足约束条件的的应用程序就是RESTful
3:HTTP方法
REST基本架构的四个方法
- GET:用于获取数据
- PUT:用于添加数据
- DELETE:用于删除数据
- POST:用于添加和更新数据
- HEAD:获取资源的元数据。
- OPTIONS:获取信息,关于资源的哪些属性是客户端可以改变的。
- PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。
4:Web Services
Web Services 是一个平台独立的,低耦合,自包含的,基于可编程的web应用程序,可使用xml标准来描述,发布,发现,协调和配置这些应用程序,用于开发分布式的互操作的应用程序
由于http直接传输数据,RESTful Web Services成为替代方法
5:RESTful基本概念
网站的访问就是你客户端和服务端的一种交互,在这种交互中,涉及到数据和转态的变化。互联网http协议是一种无状态协议,
所有状态都是保存在服务器上如果客户端想要操作服务器,必须通过某种手段,让服务器端发生"状态转化"(State Transfer)。而这种转化是建立在表现层之上的,所以就是"表现层状态转化"。客户端用到的手段,只能是HTTP协议。具体来说,就是HTTP协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源。
- 每一个URI代表一种资源;
- 客户端和服务器之间,传递这种资源的某种表现层;
- 客户端通过四个HTTP动词,对服务器端资源进行操作,实现"表现层状态转化"。
- 因为"资源"表示一种实体,所以应该是名词,URI不应该有动词,动词应该放在HTTP协议中。
1):资源和URI
REST说的是表述性转态转移,指的是资源的表述,在网路中,任何被引用的对象都是一个资源,既可以是具体的实体(手机号),也可以是抽象对象(关系,价值等)。
资源是可以被唯一标识的,URI(Uniform Resource Identify),统一资源定位符
URI设计的技巧:
- 使用_或-来让URI可读性更好:http://www.oschina.net/news/38119/oschina-translate-reward-plan。
- 使用/来表示资源的层级关系:https://github.com/qq1157918444/css3-demo
- 使用?用来过滤资源,不仅仅是参数传递
2):统一资源接口
RESTful使用统一的接口,接口使用标准的http四大方法,并准守这些方法的语义,
- GET:
- 安全且幂等
- 获取表示
- 变更时获取表示(缓存)
- 200(OK) - 表示已在响应中发出
- 204(无内容) - 资源有空表示
- 301(Moved Permanently) - 资源的URI已被更新
- 303(See Other) - 其他(如,负载均衡)
- 304(not modified)- 资源未更改(缓存)
- 400 (bad request)- 指代坏请求(如,参数错误)
- 404 (not found)- 资源不存在
- 406 (not acceptable)- 服务端不支持所需表示
- 500 (internal server error)- 通用错误响应
- 503 (Service Unavailable)- 服务端当前无法处理请求
- post
- 不安全且不幂等
- 使用服务端管理的(自动产生)的实例号创建资源
- 创建子资源
- 部分更新资源
- 如果没有被修改,则不过更新资源(乐观锁)
- 200(OK)- 如果现有资源已被更改
- 201(created)- 如果新资源被创建
- 202(accepted)- 已接受处理请求但尚未完成(异步处理)
- 301(Moved Permanently)- 资源的URI被更新
- 303(See Other)- 其他(如,负载均衡)
- 400(bad request)- 指代坏请求
- 404 (not found)- 资源不存在
- 406 (not acceptable)- 服务端不支持所需表示
- 409 (conflict)- 通用冲突
- 412 (Precondition Failed)- 前置条件失败(如执行条件更新时的冲突)
- 415 (unsupported media type)- 接受到的表示不受支持
- 500 (internal server error)- 通用错误响应
- 503 (Service Unavailable)- 服务当前无法处理请求
- PUT
- 不安全但幂等
- 用客户端管理的实例号创建一个资源
- 通过替换的方式更新资源
- 200 (OK)- 如果已存在资源被更改
- 201 (created)- 如果新资源被创建
- 301(Moved Permanently)- 资源的URI已更改
- 303 (See Other)- 其他(如,负载均衡)
- 400 (bad request)- 指代坏请求
- 404 (not found)- 资源不存在
- 406 (not acceptable)- 服务端不支持所需表示
- 409 (conflict)- 通用冲突
- 412 (Precondition Failed)- 前置条件失败(如执行条件更新时的冲突)
- 415 (unsupported media type)- 接受到的表示不受支持
- 500 (internal server error)- 通用错误响应
- 503 (Service Unavailable)- 服务当前无法处理请求
- DELETE
- 不安全但幂等
- 删除资源
- 200 (OK)- 资源已被删除
- 301 (Moved Permanently)- 资源的URI已更改
- 303 (See Other)- 其他,如负载均衡
- 400 (bad request)- 指代坏请求
- 404 (not found)- 资源不存在
- 409 (conflict)- 通用冲突
- 500 (internal server error)- 通用错误响应
- 503 (Service Unavailable)- 服务端当前无法处理请求
- POST和PUT在创建资源的区别在于,所创建的资源的名称(URI)是否由客户端决定。
- 一些比较古老的基于浏览器的客户端,只能支持GET和POST两种方法。rails框架就支持通过隐藏参数_method=DELETE来传递真实的请求方法。Backbone这样的客户端MVC框架则允许传递_method传输和设置X-HTTP-Method-Override头来规避这个问题。
- 统一接口并不阻止你扩展方法,只要方法对资源的操作有着具体的、可识别的语义即可,并能够保持整个接口的统一性。像WebDAV就对HTTP方法进行了扩展,增加了LOCK、UPLOCK等方法。而github的API则支持使用PATCH方法来进行issue的更新,像PATCH这种不是HTTP标准方法的,服务端需要考虑客户端是否能够支持的问题。
- 统一资源接口要求使用标准的HTTP方法对资源进行操作,所以URI只应该来表示资源的名称,而不应该包括资源的操作。
- 禁止缓存机制。 最简单的做法就是在你的HTTP响应里增加这样一个报头: Cache-control: no-cache。 但是,同时你也对失去了高效的缓存与再验证的支持(使用Etag等机制)。对于客户端来说,在为一个REST式服务实现程序客户端时,也应该充分利用现有的缓存机制,以免每次都重新获取表示。
3):资源的表述
客户端获取的只是资源的表述而已。 资源在外界的具体呈现,可以有多种表述(或成为表现、表示)形式,在客户端和服务端之间传送的也是资源的表述,而不是资源本身。 例如文本资源可以采用html、xml、json等格式,图片可以使用PNG或JPG展现出来。
客户端可以通过Accept头请求一种特定格式的表述,服务端则通过Content-Type告诉客户端资源的表述形式。
Content-type:application/json;charset=utf-8
Content-type:application/xml;charset=utf-8
Content-type:application/plain;charset=utf-8
Content-type:application/html;charset=utf-8
在URI里边带上版本号
使用URI后缀来区分表述格式
像rails框架,就支持使用/users.xml或/users.json来区分不同的格式。 这样的方式对于客户端来说,无疑是更为直观,但混淆了资源的名称和资源的表述形式。
如何处理不支持的表述格式
当服务器不支持所请求的表述格式,那么应该怎么办?若服务器不支持,它应该返回一个HTTP 406响应,表示拒绝处理该请求。
4):资源的链接
REST不仅仅是CURD的Web数据库架构,而且利用了超媒体的概念,把一个个把资源链接起来.
5):状态的转移
状态应该区分应用状态和资源状态,客户端负责维护应用状态,而服务端维护资源状态。
客户端与服务端的交互必须是无状态的,并在每一次请求中包含处理该请求所需的一切信息。
服务端不需要在请求间保留应用状态,只有在接受到实际请求的时候,服务端才会关注应用状态。
这种无状态通信原则,使得服务端和中介能够理解独立的请求和响应。
在多次请求中,同一客户端也不再需要依赖于同一服务器,方便实现高可扩展和高可用性的服务端。
浏览器随各次请求发出去的Cookie是被用于构建会话状态的。
当然,如果Cookie保存的是一些服务器不依赖于会话状态即可验证的信息(比如认证令牌),这样的Cookie也是符合REST原则的。
"会话"状态不是作为资源状态保存在服务端的,而是被客户端作为应用状态进行跟踪的。客户端应用状态在服务端提供的超媒体的指引下发生变迁。服务端通过超媒体告诉客户端当前状态有哪些后续状态可以进入。
API的设计
1:协议
API与用户的通信协议,总是使用HTTPs协议。
2:域名
应该尽量将API部署在专用域名之下。
https://api.example.com
如果确定API很简单,不会有进一步扩展,可以考虑放在主域名下。
https://example.org/api/
3:版本(Version)
应该将API的版本号放入URL。
https://api.example.com/v1/
将版本号放在HTTP头信息中,
4:路径
表示API的具体网址。
https://api.example.com/v1/a
https://api.example.com/v1/b
https://api.example.com/v1/c