NO END FOR LEARNING

Writing blog if you feel tired | 学海无涯 苦写博客

理解设计RESTful API - 资源、表述和HTTP协议语义

| Comments

什么是资源?什么是表述?

就本质而言,任何足够重要并被引用的事物都可以是资源。如果你的用户“想要建立指向它的超文本链接,指出或者反对关于它的断言,获取或者缓存它的表述,共另外的表述引用它的全部或者部分,给它增加注释信息,或者对它执行某些操作”,(源自《万维网的架构》),你都应该将它定义为资源。

每个资源必须拥有URL,在web上,我们使用URL来为每个资源提供一个全球唯一的地址,将一个事物赋以URL,它就会成为一个资源。

石榴可以是一个资源,但是你不可能通过互联网传输它,数据库中的一条记录可以是一个资源,并且可以通过互联网传输。

当客户端对一个资源发起一个Get请求的时候,服务器会以一种有效的方式提供一个采集了资源信息的文档作为回应。这种资源信息的文档就是一种表述,一种以机器可读的方式对资源当前的状态进行说明。

资源有多重表述

一个资源可以有多种表述。比如,有的资源可以有整体概括性的表述,也可以有面面俱到的详细表述,又或者可能以JSON格式或者XML格式来表述同一个资源。

约束 - HTTP协议语义

尽管任何事物都可以成为一个资源,但是客户端并不能随心所欲地对资源进行任意的操作。所能进行的操作是有规定的。在一个RESTful系统里,客户端和服务器端只能通过相互发送遵循预定义协议的消息来进行交互。在Web API的世界里,该协议就是HTTP。

在设计Web API时,严格遵守HTTP协议语义是设计好的API的重要基础。

GET请求

客户端通过发送Get请求来获取某个URL所标示的资源的表述。Get被定义为安全的HTTP方法。它仅仅是对信息的一次请求。向服务器发送一条Get请求对资源的影响应该和没有发送一样。

DELETE请求

发送DELETE请求,客户端希望服务器将资源销毁,并且以后再也不会跳到它。当Get请求再次访问一个已经销毁的资源,服务器应该返回错误响应码,比如404(Not Found)。Delete不是一个安全的方法,它会改变资源的状态,但是DELETE方法有另外一个很重要的属性,就是幂等性。当你发送一个DELETE请求后,资源就永久性的消失了,即便之后,再次发送相同的DELETE请求,也许你会收到404的错误码,但是第二次发送后和第一次发送后,资源的状态是一致的,仍然不存在。

幂等性是一个很重要的特性,因为互联网的不稳定性,假设发送的一个Delete请求,因为连接超时,你并没有收到响应,所以你无法知道发送的Delete请求是否顺利完成,这时你也许会发送第二次Delete请求。幂等性保证了执行两次Delete请求并不会比执行一次Delete请求给资源带来更多的影响。

POST-to-Append请求

为什么是Post-to-Append而不是Post呢?因为Post方法可以做两件事情,第一件事情就是Post-to-Append,第二件事情叫做overloaded post。我们先看POST-to-Append,向某个资源发送一条Post请求用以在该资源的下一级中创建新的资源,当客户端发送一个POST-to-Append请求时,它会在请求的实体消息体中添加所希望创建的资源的表述信息并发给服务器。Post方法既不安全也不幂等,如果发送多次Post请求,就会创建多个资源。

PUT请求

Put请求用于修改资源的状态。客户端一般会通过Get请求获取表述,然后对其进行修改,最后再将修改后的资源表述作为PUT请求的负载数据发送回去。PUT请求也是幂等的,无论发送多少次PUT请求,结果都和第一次发送PUT请求一样。


以上4种请求,我们最常见也是使用最频繁的请求。接下来要介绍的请求,虽然见的不多,但是当你了解后,你会觉得它非常有用。

PATCH请求

表述的信息量可能非常大。虽然,我们可以使用PUT请求来修改资源,但是如果只想修改资源状态的部分,或者说很少一部分,才PUT就会造成极大的资源浪费,这对于移动应用所使用的Web API设计是非常重要的。和将完整信息发送过去的PUT方法不同,PATCH方法将一个“diff”的表述放在请求的负载数据中发送给服务器。

HEAD请求

Head方法是和Get方法一样的安全方法。服务器应该和处理Get方法一样除了Head方法,但是Head方法不需要发送实体消息,只需要发送HTTP状态码和报头。

OPTIONS请求

OPTIONS是HTTP的原生探索机制。一个OPTIONS请求的返回结果包含一个HTTP Allow报头,这个报头展示了这个资源所支持的所有HTTP方法。

肮脏的Overloaded POST请求

POST不仅仅被用于创建新的资源,在用浏览器上网的时候,POST也被用于传输任何形式的变化,它将PUT、DELETE、PATCH、LINK和UNLINK所有的方法混合成一个方法。

比如,在页面有一个表单对用户的基本信息进行修改,它是一个POST请求,但是从语义上,它更像是一个PUT,但这完全是合法的,任何数据作为POST请求的一部分发出去,不论是出于什么目的,这都是合法的。这导致POST请求没有任何语义。由于重载后的POST请求可以用来完成任何事情,所以这种POST方法既不安全也不幂等。


好的API不应该依靠文档来维护它的使用方式,就好像是优秀的代码,不需要注释来考诉你它是干什么,合理的协议语义的使用会帮助API实现基本的自我描述,虽然这还远远不够,但它最起码是互联网上大家都遵守的约束。

参考资料:
1. RESTful Web AIPs

Comments