复杂的系统总是由简单的系统演变而来的。.
—John Gall
Systemantics
我们写这本书,是要告诉你一项令人瞩目的新技术。喏,它很热门,它会彻底改变我们编写分布式系统的方式。我们要讲的是万维网(World Wide Web,简称Web)。
没错,Web 不是什么新技术,也不如昔日那么火了,而且从技术角度来看,它并不是那么令人瞩目。但它的确改变了我们许多。这10 年来,Web 已经改变了我们生活的方式;不过,更多潜在的改变将等待我们。Web 是简单的、无所不在的;然而,它作为分布式编程平台的潜力却被忽视了。我们编写本书的目的,就是要让大家体验Web 的这种潜力。说Web 作为分布式编程平台的潜力被忽视了,这听上去也许令人感到诧异。毕竟,本书还要与其他Web 服务相关书籍竞争。问题是,大部分如今的“Web 服务”都与Web 毫无干系。它们采用像COM、CORBA 那样的重量级分布式对象访问架构——这与Web 的简单性背道而驰。如今的“Web 服务”架构重复或忽略了Web 赖以成功的每一种特性。其实并不需要那样。Web 背后的(underlying)技术足以支撑强大的远程服务——其实那些服务就存在着,而且我们每天都在使用它们。这种服务可以延伸到巨大的规模——其实这已经实现了。以Google 搜索引擎为例,它不就是一个对海量数据库进行查询并返回结构化搜索结果的远程服务吗?通常,我们不把网站(web site)当作“服务(service)”来看,因为网站的最终用户是人,而服务是程序之间的对话。但网站就是服务。每个Web 应用(包括每个网站)都是一个服务(service)。只要遵从Web 的理念而不是违反它,只要不把Web 特有的能力隔离在很多层抽象之下,你就能够让可编程应用(programmableapplications)利用这种能力。现在是让“Web 服务”回归“Web”理念的时候了。
《RESTful Web Services中文版》官方网站 http://restfulwebservices.cn
令网站易于被上网者使用的那些特性,同样也令Web 服务API 易于被程序员所使用。为寻找服务的设计原则,我们可以从网站的设计原则着手,并思考如果网站的使用者不是人而是程序,那最终将得到什么样的设计原则。
本书就是这么做的。我们的中心目标,就是展示Web 基础技术(HTTP 应用协议、URL命名标准、XML 标记语言)的强大能力、适用场合及局限等。本书主要讲的是Web 背后的(underlying)一套设计原则——表示性状态转移(Representational State Transfer),或简称为REST。我们率先为“REST 式(RESTful)”Web 服务提出了最佳实践(best practices)。我们不会采用含糊或臆断性的语言,相反,将用具体的建议来取代那些坊间传言(folklore)和隐性知识。
我们引入了面向资源的架构(Resource-Oriented Architecture,ROA)作为用于设计REST式Web 服务(RESTful web services)的一组切合实际的原则。我们还会教你如何编写客户端程序来调用REST 式服务。我们将采用一些真实的REST 式服务作为案例,比如:Amazon S3(Simple Storage Service)、各种Atom 发布协议的变形,以及Google Maps 等。我们也会举一些流行的但不符合REST 原则的例子(比如 del.icio.us 的社会性书签API),然后对它们进行重构。
简单的Web
The Web Is Simple
为何我们对Web 如此着迷,以至于认为它能解决所有问题?也许我们上当了,成为炒作的受害者。尽管HTTP 并不是最受欢迎的Internet 协议,但Web 无疑是被炒作得最凶的一种Internet 技术。据统计,全球Internet 流量中的大部分源自电子邮件(归因于垃圾邮件)或BitTorrent(归因于侵犯版权)。假如明天Internet 就不复存在,那么人们最为怀念的将是电子邮件。那为何要如此重视Web 呢?是什么使得HTTP——一种为物理实验室之间传递研究记录而设计的协议——同时能够适合分布式Internet 应用呢?
实际上,说HTTP 是为某某目的而设计的,对它是一种极大的恭维。已经有人说了,HTTP与HTML 是“Internet 协议里的放屁坐垫(Whoopee Cushion)与欢乐蜂鸣器(Joy Buzzer),只能搞些小把戏”(译注1)——这还是一个喜爱它们的人说的。(注1)第一版HTTP(即HTTP 0.9)的确看上去像是搞小把戏,比如下面这个客户端与服务器交互的例子:客户端请求 服务器响应
GET /hello.txt Hello, world!
译注1:屁坐垫和欢乐蜂鸣器都是廉价的整人玩具。放屁坐垫(Whoopee Cushion)是一种充气坐垫,当人坐上去后会发出放屁似的声音。欢乐蜂鸣器(Joy Buzzer)是一种装置,当佩戴此装置的人与人握手时,它会发出剧烈振动和蜂鸣声。这个比喻的言下之意是说,HTTP 与HTML 是不起眼的,只能搞些小把戏,做不了正经事。
注1:Clay Shirky,《In Praise of Evolvable Systems》(http://www.shirky.com/writings/evolve.html)。《RESTful Web Services中文版》官方网站 http://restfulwebservices.cn
就这么简单。你连接到服务器,把文档路径给它,然后服务器就把文档内容返回给你。
HTTP 0.9 差不多就只支持这么些了,看似只是毫无特色地照搬比它复杂一点的文件传输协议(FTP)。
令人意外的是,答案基本就是这样。我们可以半开玩笑地讲,HTTP 是特别适合分布式Internet 应用的,因为它没有值得一提的特性。你讲要什么,它就给什么。跟功夫片里的手法同出一辙,(注2)HTTP 的缺点转化成了优势,它的简单性转化成了强大能力。
HTTP 0.9 是特地设计成那么简单的。从HTTP 0.9 中我们可以看到可寻址性(addressability)和无状态性(statelessness)——正是这两条基本设计原则,令HTTP 较其同类更加优秀,并得以延伸到今天如此巨大的规模。在HTTP 0.9 所缺少的特性中,大部分已被证实是多余的,甚至是有副作用的(其实,添加那些特性将有损于Web),而其余的许多特性已在HTTP 1.0 和1.1 版中实现了。Web 赖以成功的另两项重要技术是URL 和HTML(以及后来的XML)——它们在许多重要方面也是简单的。
. 显然,这些“简单的”技术在功能上已足够强大,它们支持Web 及Web 上的应用。在本书中,我们进一步提出:万维网(World Wide Web)是一个简单而灵活的分布式编程环境。而且我们认为其原因是:为人类使用而设计的human web,跟为软件程序调用而设计的“programmable web”没有本质区别。我们认为,如果Web 能很好地为人类所用,那么它也同样能很好地为程序所用。我们只要多作一些考虑即可。计算机程序擅长于构建和解析复杂的数据结构,但是在理解文档方面,它们无法做到像人类一样灵活。
复杂的大Web 服务
Big Web Services Are Not Simple
用作构建Web 服务的协议与标准有很多,它们大多是构筑在HTTP 之上的。这些标准被统称为WS-*标准栈。它们包括WS-Notification、WS-Security、WSDL 及SOAP 等。在本书中,我们用“大Web 服务(Big Web Services)”来称呼这些技术,以较为礼貌地表达我们对它的鄙视。
本书不对这些标准作详细介绍。我们觉得,实现Web 服务并不一定非得用大Web 服务(BigWeb Services),相反,用Web 就足够了。我们相信,Web 基础技术足以成为默认的分布式服务平台。
对于某些WS-*标准(例如SOAP),你可以做到使用它们,而不违反REST 及面向资源的架构(Resource-Oriented Architecture)。但实际上,它们被用于实现基于HTTP 的远程过注2:《Legend of The Drunken Protocol》(1991)
《RESTful Web Services中文版》官方网站 http://restfulwebservices.cn
程调用(Remote Procedure Call,RPC)。 有时,采用RPC 式架构是合适的;有时,有比Web 的优点更为重要的需求得考虑。这没关系。
不必要的复杂性是我们所不期望的。有些场合,采用普通老式的HTTP(plain old HTTP)就足以应付了,但程序员或公司却经常采用大Web 服务(Big Web Services)。这样做的效果是,HTTP 成为一种用于传输庞大XML 负载(payload)的协议,而“真正的”描述信息在XML 里。最终的服务变得太过复杂、难于调试,而且要求客户端必须与服务端具备同样的配置环境。
大Web 服务(Big Web Services)确实有个优点:现今的开发工具使你只需点一下鼠标,就可以根据代码生成Web 服务(尤其是Java 或C#开发)。在用这些工具来生成符合WS-*标准栈的RPC 式Web 服务时,REST 式Web 服务的简单性这一优点对你来说也许已经不重要了,因为这些工具已经隐藏了所有的复杂性,不用让你操心。毕竟带宽和CPU 都便宜。
假如是在同质(homogeneous)环境中,且服务都在同一个防火墙之后的话,那么这种做法是可行的。如果你的机构有足够的政治影响力,可以要求防火墙外的其他机构也采用跟你们同样的方式。但是,假如期望服务逐渐发展到Internet 规模,就必须能够应付没有事先考虑到的客户端,比如采用你从没想到的自定义软件栈(software stacks)来访问服务。用户会试图把你的服务与其他你没听说过的服务集成起来。貌似很难?这在Web 上已经司空见惯了。
抽象(abstraction)也不是完美的。每增加一个层次,就多一些故障点(failure point)、互操作难题和可伸缩性问题。现代化开发工具能够隐藏复杂性,但它们无法为引入复杂性解释原因——它们就知道不断地增加层次。要令服务融入Web,就要在适应性(adaptability)、可伸缩性(scalability)及可维护性(maintainability)方面多加注意。而简单性(simplicity)——HTTP 0.9 被忽视的优点——则是这三者的先决条件。系统越复杂,出错时纠正起来就越困难。
如果你提供REST 式Web 服务,可以把复杂性投入“实现更多特性、实现不同服务之间的交互”中。成功地提供服务,意味着不光把服务构筑在Web“之上”,而且应该令服务融入Web:设计服务时,应遵循跟“良好的网站设计所采用的”一样的原则。跟基本的Web 协议靠得越拢,这就越容易实现。
关于REST
The Story of the REST
REST 虽然简单,但它是良好定义的(well-defined);而且,不能因为“Web 服务和网站是一样的东西”,就以简单性作为“把Web 服务实现成功能贫乏的网站”的借口。可惜到目前为止,主要的REST 参考文献只有Roy Fielding 2000 年的博士论文第5 章——就博士论文来说,那是很好的资料;不过对于大部分现实问题,它并没有给出回答。(注3)这是因为,那篇博士论文不是把REST 作为一种架构来诠释,而是把REST 当作一种评判架《RESTful Web Services中文版》官方网站 http://restfulwebservices.cn
构的方法来介绍的。“REST 式(RESTful)”这个术语就像“面向对象(object-oriented)”这个术语一样。一门语言、一种框架或一个应用也许是采用面向对象的方法设计的,但这并不一定确保其架构是面向对象的架构。(注3)
即使采用像C++或Ruby 这样面向对象语言,也有可能写出不是真正面向对象的程序出来。按照REST 的标准,HTTP 在理论上是很好的。(这是理所当然的,因为Fielding 参与了HTTP 标准的编写,而且他在博士论文里描述了Web 的架构。)不过,在现实中,网站、Web 应用及Web 服务等经常与REST 原则相违背。那么,在对具体的Web 服务进行设计时,你怎样才能确信自己正确运用了REST 原则呢?
大部分关于REST 的信息来源都是非正式的:邮件列表(mailing list)、Wiki、博客等(我在附录A 中给出了一些很好的链接)。直至如今,REST 的最佳实践(best practices)还只是一些坊间传言(folklore)。所需要的,是一个以REST 元架构(meta-architecture)为基础的具体架构(architecture):一套为设计“体现了Web 的潜力”的服务而制定的基本准则——我们将在第4 章介绍这样一种架构,即面向资源的架构(Resource-OrientedArchitecture,简称ROA)。它并不是唯一的高层(high-level)REST 式架构,但是我们认为,用它来设计“易于为客户端所用”的Web 服务是很好的。
我们通过制定这个面向资源的架构(ROA),把来自坊间传言(folklore)的经验提炼为Web 服务设计的最佳实践(best practices)。它们仅作为一个建议的基线(suggestedbaseline)。如果你曾经力图领会REST,希望我们的架构能够令你自信地认为所做的是“真正的”REST。我们也希望,面向资源的架构(ROA)能够帮助整个社区加快提出并系统化最佳实践我们希望让程序员可以轻易地构建优雅的、符合设计用途的、融入Web 的(而不是仅仅构筑在Web 之上的)分布式Web 应用。
但我们知道,你光掌握这些技术还是不够的。我们两人都曾有过这样的经历:所工作的机构,在主要的架构决策上没有按照我们的意思去做。如果没机会采用REST 式架构,你是无法在REST 式架构方面取得成功的。因为,除了技术知识以外,我们还必须教你怎样用言辞去推荐REST 式解决方案。我们已经把面向资源的架构(ROA)定位为一种替代RPC式架构(即如今的SOAP+WSDL 服务所采用的)的简单方案。RPC 式架构通过一个复杂的、编程语言式的接口,来暴露其内部算法(algorithms)——这种接口,每个服务都各不相同。而ROA 则通过一个简单的、文档处理接口,来暴露其内部数据(data)——这种接口是统一的。我们将在第10 章对这两种架构加以比较,并教你如何来推荐采用ROA。
注3:Fielding, Roy Thomas. Architectural Styles and the Design of Network-Based SoftwareArchitectures, Doctoral dissertation, University of California, Irvine, 2000 http://www.ics.
uci.edu/~fielding/pubs/dissertation/top.htm)。译注:这篇博士论文已经被国内同行翻译为中文版,可以从这里下载:http://www.redsaga.com/opendoc/REST_cn.pdf。
《RESTful Web Services中文版》官方网站 http://restfulwebservices.cn
统一两种Web
Reuniting the Webs..
程序员把网站作为Web 服务来用,这已经有好多年了——当然,是非正式的。(注4)要让计算机理解供人类阅读的网页,是比较困难的,但这并没有阻止程序高手们用自动化客户端来抓取网页,然后用屏幕抓取程序来提取有关信息。随着时间的推进,出现了RSS、XML-RPC 和SOAP 这些对程序员友好的技术——它们用于按正式认可的方式来暴露网站功能。这些技术形成了一种programmable web,它是对human web 的扩展,它为软件程序提供了方便。
我们写这本书的最终目的,是统一programmable web 与human web。我们设想的是单个互联的网络:一个“在一组服务器上运行,采用一套协议并遵从一组设计原则”的万维网(World Wide Web)。那是一个既可被人也可被计算机程序使用的网络。
若不是得益于分配不当的国防资金、创新的工程项目、“差点则更好”(worse-is-better)的工程实践、大科学、天真的自由理想主义、古怪的自由主义政治、技术迷信,以及那些认为自己找到了发财之路的程序员和投资者的汗水与资本,因特网(Internet)和万维网(World Wide Web)也许不一定会诞生。
Web 作为一个简单的、开放的(至少现阶段)和基本统一的网络应用平台,它容纳了大量的人类知识,并为人类所努力钻研的许多领域提供支持。我们认为,现在应该开始认真考虑将网站设计原则应用于服务设计,以便自动化客户端可以访问那些信息和算法。假如同意的话,本书将教你怎么做。
本书的内容
What’s in This Book?
在本书中,我们主要关注一些实际问题:如何设计与实现REST 式Web 服务(RESTful WebServices),以及调用它们的客户端。其次我们还关注于理论方面:什么是REST 式架构风格?为什么Web 服务应该尽量符合REST 风格?我们的讨论不会涵盖方方面面,但是力图切入如今的重点话题。因为这是同类书中的第一本,我们会不断反复这一关键问题——即如何设计一个REST 式服务。
前3 章,将从客户端的角度来介绍Web 服务,并告诉你REST 式服务有什么特别不同。
注4:一个早期的例子,请参见Jon Udell 于1996 年发表在《Byte》杂志上的文章《On-LineComponentware》(http://www.byte.com/ art/9611/sec9/art1.htm)。注:“A powerful capabilityfor ad hoc distributed computing arises naturally from the architecture of the Web.”——大家注意了,这句话1996 年就讲了。
《RESTful Web Services中文版》官方网站 http://restfulwebservices.cn
第1 章 Programmable Web 及其分类
我们在这一章对Web 服务作总体性介绍。Web 服务运行于Web 上,请求外部服务器提供数据或运行算法的程序。我们将展示三种常见的Web 服务架构:REST 式架构、RPC 式架构及REST-RPC 混合架构。我们会为每一种架构举一个HTTP 请求/响应的例子,并给出典型的客户端代码。
第2 章 编写Web 服务客户端
在这一章,我们教你如何用HTTP 库和XML 解析器来为现有Web 服务编写客户端。我们将介绍一个流行的REST-RPC 服务——del.icio.us Web 服务,并用Ruby、Python、Java、C#及PHP 等语言来示范其客户端代码。 对于其他一些语言,我们虽然没有展示代码,但会推荐一些适用的HTTP 库和XML 解析器。JavaScript 和Ajax 将在第11章中作单独介绍。
第3 章 REST 式服务有什么特别不同?
我们将吸取第2 章的经验,并把这些经验运用于一个纯REST 式服务——Amazon S3(Simple Storage Service)。我们将在构建S3 客户端时举例说明一些重要的REST 概念:资源(resource)、表示(representation)、统一接口(uniform interface)。
下面6 章是本书的核心,它们关注于如何设计和实现自己的REST 式服务。
第4 章 面向资源的架构
本章正式介绍REST:不是抽象地介绍,而是以一个具体的Web 服务架构为背景进行介绍。我们的架构基于四个重要的REST 概念:资源、资源名称、资源表示(representation),以及资源间的链接。它的服务应根据四个REST 特征来评判:可寻址性、无状态性、连通性和统一接口。
第5 章 设计只读的面向资源的服务
我们提出了“把想法或需求转变为REST 式资源”的系列步骤。这些资源是只读的,也就是说客户端可以从服务获取数据,但是不能改变服务的数据。我们以一个设计地图服务(类似Google Maps)的例子来说明这些步骤。
第6 章 设计可读写的面向资源的服务
我们扩展了上一章的步骤,以允许客户端创建、修改并删除资源。我们以为地图服务新增两种资源(用户账户和自定义地点)为例,示范这些步骤。
第7 章 一个服务实现
我们把一个RPC 式服务(即第2 章那个del.icio.us REST-RPC 混合服务)重构为一个纯REST 式服务。然后,我们把这个服务实现为一个Ruby on Rails 应用。通过这一章,你可以把所学到的知识操练一遍!
《RESTful Web Services中文版》官方网站 http://restfulwebservices.cn
第8 章 REST 和ROA 最佳实践
在这一章,我们把之前给出的关于服务设计的建议汇集起来,并补充一些新的建议。我们将告诉你如何利用HTTP 的标准特性来解决常见问题和进行优化。我们还将为棘手的特性(比如事务,也许你认为这没法用REST 式Web 服务来实现)给出面向资源的设计。
第9 章 服务的技术构件
我们在这一章描述在REST 的三大技术(HTTP、URI 和XML)之上的其他技术:有些是用于传递状态的文档格式,比如XHTML 及其微格式(microformat);有些是用于为客户端状态推进的超媒体格式,比如WADL;有些是用于构建REST 式Web 服务的控制流,比如Atom 发布协议。
最后3 章涉及一些专门话题,这些专题各自都可单独作为一本书来讨论。
第10 章 面向资源的架构 VS 大Web 服务
将拿我们的架构及一般的REST 架构跟其他著名架构来进行比较。我们认为REST 式Web 服务较“基于SOAP、WSDL 和WS-*”的服务而言,更为简单、可伸缩性更好、更易于使用、更加符合Web 的理念,且更能应付各种各样的客户端。
第11 章 将Ajax 应用作为REST 客户端
在这一章,我们将以Web 服务来阐述用于Web 应用的Ajax 架构:一个Ajax 应用,就是一个在浏览器里运行的Web 服务客户端。本章是对第2 章内容的延伸。我们教你如何用XMLHttpRequest 和标准的JavaScript 库来编写用于REST 式Web 服务的客户端。
第12 章 REST 式服务框架
在最后这一章里,我们将讨论三种流行的框架:Ruby on Rails、Restlet(用于Java)和Django(用于Python)。它们可以简化REST 式Web 服务的开发。
我们还有3 个附录,希望对你有用。
附录A REST 相关资源与REST 式资源
第一部分列出了一些与REST 式Web 服务有关的标准、教程和社区。第二部分给出了一些现有的、公开的、可供你调用和学习的REST 式Web 服务。
附录B 42 种常见的HTTP 响应代码
这部分解释标准HTTP 的每一个响应代码(以及一个扩展),并解释何时你会在REST式Web 服务里用到这些代码。
附录C 常见的HTTP 报头
这部分向你解释各种HTTP 报头,包括每个标准的HTTP 报头,以及一些用于Web服务的扩展报头。
《RESTful Web Services中文版》官方网站 http://restfulwebservices.cn
你应该阅读哪些部分?
本书的组织,适于那些对Web 服务的概况感兴趣的读者:有些读者通过实践学习Web服务,但他们对于Web 服务没有太多经验。如果你属于这种情况,可以采取一条最简化的阅读路线,即从本书开头一直读到第9 章,然后在剩下的章节中选择你所感兴趣的部分。
如果你经验比较丰富,那么可以采取另一种阅读路线。如果你关心如何为现有服务编写客户端,那么可以只关注第1、2、3 和11 章——那些关于服务设计的章节对你可能帮助不大。如果你想要创建自己的Web 服务,或者想知道REST 到底是什么意思,你不妨从第3 章开始阅读。如果你想比较REST 与WS-*,那么你可以选第1、3、4 和10章作为起点。
说明
Administrative Notes
本书有两位作者(Leonard 和Sam),在本书的1-11 章,我们将把这两个身份合并为第一人称“我”。而在最后一章(第12 章)里,这个第一人称“我”代表的是一大群人,因为有众多Django 和Restlet 开发者们参与到“展示如何用他们的框架来构建REST 式服务”中来。
我们假定你是一名胜任的程序员,但不假定你在Web 编程方面有任何经验。我们在书中介绍的内容并不限定于某一编程语言。我们提供了以各种语言编写的REST 式客户端及服务的示例代码。除非为了示范特定的框架或语言,否则我们将采用Ruby(http://www.rubylang.org)语言来描述。
我们选用Ruby 是因为:即使对于不懂Ruby 的程序员来说,它也是简洁易读的。(因为这是一门很好的语言,而且它的名字跟Sam 的姓有着令人困惑的联系。)Ruby 的标准Web框架——Ruby on Rails——也是最主要的一种REST 式Web 服务实现平台之一。如果你不懂Ruby 也没关系,我们在代码中嵌入了许多有助于理解Ruby 语法的注释。
本书的示例程序可以从本书官方网站(http://www.oreilly.com/catalog/9780596529260)上下载,其中包括第7 章的Rails 应用的完整代码,以及第12 章中Restlet 和Django 应用的相应代码。在书中,许多客户端我们只给出了Ruby 实现;但在示例程序中,你还可以找到它们的Java 实现。这些客户端程序采用了Restlet 库,并且是由Restlet 开发者JeromeLouvel 和Dave Pawson 编写的。若相对Ruby 而言,你更熟悉Java,那么这些代码对你掌握代码背后的概念会有帮助。特别值得注意的是,示例代码里还包括一个完整的第3 章Amazon S3 客户端的Java 实现。
《RESTful Web Services中文版》官方网站 http://restfulwebservices.cn
一些约定
Conventions Used in This Book
书中字体将采用以下约定:
Italic(斜体)
表示新术语、URI、Email 地址、文件名及文件扩展名。
Constant width(等宽字体)
用于程序代码,以及变量、函数名、数据库、数据类型、环境变量、声明和关键字等。
Constant width bold(等宽粗体)
用于命令行及其他应由用户逐字输入的文本。
Constant width bold(等宽斜体)
用于应替换为用户提供或由上下文决定的值 的文本。
这个图标表示一则技巧、提示或普通的注解。
这个图标表示一则警告或注意。
《RESTful Web Services中文版》官方网站 http://restfulwebservices.cn
联系我们
How to Contacts Us
我们已尽力核验本书所提供的信息,尽管如此,仍不能保证本书完全没有瑕疵,而网络世界的变化之快,也使得本书永不过时的保证成为不可能。如果读者发现本书内容上的错误,不管是赘字、错字、语意不清,甚至是技术错误,我们都竭诚虚心接受读者指教。如果您有任何问题,请按照以下方式与我们联系。
奥莱理软件(北京)有限公司
北京市 西城区 西直门南大街2 号 成铭大厦C 座807
邮政编码:100035
网页:http://www.oreilly.com.cn
E-mail:info@mail.oreilly.com.cn
与本书有关的在线信息如下所示。
http://www.oreilly.com/catalog/9780596529260(原书)
http://www.oreilly.com.cn/book.php?bn=978-7-121-06227-8(中文版)《RESTful Web Services中文版》官方网站 http://restfulwebservices.cn
致谢
Acknowledgments
最后,我们要感谢那些令我们得以直接在HTTP 上编程的人们。对于Sam 来说,是Rael Dornfest 和他的Blosxom 博客应用。Leonard 的经验来自于20 世纪90 年代中期编写屏幕抓取应用。他感谢那些把网站作为Web 服务来设计的人们,特别是那位在线连环画“Pokeythe Penguin”的匿名作者。
我们曾有过这样的想法,不过是Roy Fielding 充实了它。对于我们,那只是一种感觉,而Roy Fielding 则在他的博士论文里命名并定义了它。Roy 的理论基础正是我们所赖以为基础的。
在本书编写过程中,我们从REST 社区获得了巨大的帮助。我们非常感激给我们反馈的人:Benjamin Carlyle、David Gourley、Joe Gregorio、Marc Hadley、Chuck Hinson、Pete Lacey、Larry Liberto、Benjamin Pollack、Aron Roberts、Richard Walker 和Yohei Yamamoto。还有一些人通过他们的作品在不知不觉中帮助我们:Mark Baker、Tim Berners-Lee、Alex Bunardzic、Duncan Cragg、David Heinemeier Hansson、Ian Hickson、Mark Nottingham、Koranteng Ofosu-Amaah、Uche Ogbuji、Mark Pilgrim、Paul Prescod、Clay Shirky、Brian Totty和Jon Udell。当然,书中的所有看法及可能存在的错误与疏漏都是我们自己的责任。
在本书编写过程中,编辑Michael Loukides 为我们提供了很多帮助与智慧。我们还要感谢Laurel Ruma 和其他所有为本书出版付出劳动的O’Reilly 同事们。
最后,需要特别感谢的是Jerome Louvel、Dave Pawson 和Jacob Kaplan-Moss。他们在Restlet 和Django 方面的经验令我们有了本书的第12 章。...
《RESTful Web Services中文版》官方网站 http://restfulwebservices.cn