摘要: 自1994年以来,REST架构风格就被用来指导现代Web架构的设计和开发,本篇描述了在创作超文本移交协议(HTTP)和统一资源标识符(URI)两个互联网规范的过程中,以及将这些技术部署在libwww-perl客户端库、Apache HTTP服务器项目、协议标准的其他实现的过程中,应用REST所学到的经验和教训
正文:
将REST应用于URI
Web标准化
开发REST的动机是为Web的运转方式创建一种架构模式,使之成为Web协议标准的指导框架。REST被用来描述期待的Web架构,帮助识别出现有的问题,对各种替代方案进行比较,并且保证协议的扩展不会违反使Web成功的那些核心架构约束。
行业内的压力不断增长,要求对Web接口协议的某个版本或某些版本进行标准化。Berners-Lee(Web之父)创建了W3C,将其作为Web架构的智库,并为Web编写规范以及实现相关所需的资源,但是标准化本身是由IETF及其URI、HTTP和HTML工作组来掌管的。由于作者在开发Web软件方面的经验被IETF选出来创作相对URL的规范,后来又与Henrik FrystykNielsen共同创作了HTTP/1.0规范,后来Fielding博士成了HTTP/1.1的主要架构师,并且最终创作了URI通用语法标准的URL规范的修订版
REST的第一版开发于1994年10月和1995年8月之间,起初是作者Fielding博士作为编写HTTP1.0的一种概念方法。在随后的5年中以迭代的方式不断改进,并且用于各种Web协议标准的修行版和扩展之中。REST最初被称作“HTTP对象模型”,很容易被误解为它使一个HTTP服务器的实现模型,而REST(表述性状态移交)是有意唤起人们对于一个设计良好的Web应用如何运转的印象:Web应用是一个由网页组成的网络(一个虚拟状态机),用户通过选择链接(状态迁移)在应用中前进,引导系统把下一个页面(代表应用的下一个状态)的数据移交给用户,并且呈现出来,以便用户使用。其中承载包含应用状态的部分是有超媒体来负责的,这也是为什么REST强调HATEOAS(Hypermedia As The Engine Of Application Statue)的原因所在
将REST应用于URI
REST既被用来为URI规范定义“资源”这个术语,也被用来定义通过它们的表述来操作资源的通用接口的全部语义
重新定义资源
早期Web架构将URI定义为文档的标识符,创作者往往是根据网络上一个文档的位置来定义标识符,然后就能够使用Web协议来获取那个文档
然而,这个定义并不是令人满意,首先,它暗示创作者正在标识所移交的内容,这意味着任何时候当内容改变了这个标识符都应该改变(后移)。其次,存在很多地址对应的一个服务,而不是一个文档;最后,可能有一段时间没有这个文档
REST对于“资源”的定义有一个前提:标识符应该尽可能的少改变,因为Web使用内嵌的标识符而不是链接服务器。创作者需要的是一个能够与通过超媒体引用来表达的语义紧密匹配的标识符,允许这个引用保持静态,甚至是在访问该引用的结果可能会随时间而变化的情况下,REST通过将一个资源定义为创作者想要标识的语义,而不是创建引用时那些语义的对应值。然后留给创作者来保证所选择的这个标识符确实真正标识出了他所想要表达的语义
表述
把资源定义为URI标识的一个”概念”而不是具体文档,用户如何操作一个资源(“概念”)呢?
REST引入了“表述”这个中间层,即通过资源的表述来操作资源,而不是直接在资源本身上进行操作
资源和接口背后的实现细节都应该是被隐藏起来的,通过接口和表述这两个独立的概念来隔离接口和资源的这两者的具体实现,这也是REST的统一接口这个架构约束的动机。URI和HTTP组成了接口,HTML作为资源的表述,
使得来源服务器对接口和资源的具体实现得以统一化,例如基于URI和HTTP提供接口没变,服务端对应的语言变更或者架构变更对客户端来说并没有影响
将语义绑定到URI
一个资源可以拥有多个标识符,或者说存在两个或更多的不同URI在访问服务端时具有相同的语义。
对于服务器或客户端不需要知道或理解URI的含义(如在网页点击一些按钮,对于Web层来说可能只是一个POST请求而已),这个语义应该是由用户来解读
REST在URI中的不匹配
就像大多数现实中系统一样,并非所有已部署的Web架构组件都服从Web架构设计给出的每一个架构约束。
REST既可以被用作改进架构的方法,也可以被用来识别架构不匹配的地方。尽管无法避免这种不匹配,但是可以识别出他们
尽管URI的设计和REST中标识符的概念相匹配,但是仅仅依靠URI的语法规则是不足以约束不匹配的行为的。其中的一种滥用就是在所有的URL中包括标识当前用户的信息,这样的办法可以用于维护服务器会话的状态,但是也会降低共享缓存的效率,也会降低服务器的可伸缩性,并且如果一个用户把这个URL发给其他的用户时,会得到不希望看到的结果(可能看到的就是别人的数据)。这其实时违反了REST的无状态的约束。另外一个便是把Web看作是一个分布式的文件系统的时候,因为文件系统其实是暴露了其实现细节