关于REST及RESTful的概念,已有不少文章介绍,这里整理几篇我觉得不错的参考:
- 维基百科的定义: REST
- 什么是REST跟RESTful? REST理论的中文详述,其中你可以了解到WCF Restful属于RPC 样式的 Web 服务,ASP.NET Web API属于RESTful Web 服务。
- 深入浅出REST InfoQ的专文介绍,文中甚至有Roy T. Fielding当年REST博士论文的中文翻译链接。另外值得一提的,大家可能没听过Roy Fielding的大名,但如果得知他是HTTP规格的主要作者及Apache HTTP Server项目的发起人之一,应该不会有人怀疑他在Web技术领域的分量。
上面的文章建议大家认真的读一下,这里我们简要的介绍下REST 做入门介绍,理解整个 REST 能让我们在 ASP.NET Web API 的路上更顺畅。
REST是什么?
REST ( REpresentational State Transfer ),State Transfer 为 "状态传输" 或 "状态转移 ",Representational 中文有人翻译为"表征"、"具象",合起来就是 "表征状态传输" 或 "具象状态传输" 或 "表述性状态转移",不过,一般文章或技术文件都比较不会使用翻译后的中文来撰写,而是直接引用 REST 或 RESTful 来代表,因为 REST 一整个观念,想要只用六个中文字来完整表达真有难度。
REST 一词的出于《Architectural Styles and
the Design of Network-based Software Architectures》论文,我们先简单从标题来看,它应该是一种架构样式 (Architectural Styles) 与软件架构 (Software Architectures),而且是以网络 (Network-based) 为基础,重点就是:
- 架构样式 (Architectural Styles)
- 软件架构 (Software Architectures)
- 网络 (Network-based) 为基础
REST 本身是设计风格而不是标准。REST 谈论一件非常重要的事,如何正确地使用 Web标准,例如,HTTP 和 URI。想要了解 REST 最好的方式就是思索与了解 Web 及其工作方式。如果你设计的应用程序能符合 REST 原则 (REST principles),这些符合 REST 原则的 REST 服务可称为 "RESTful web service" 也称 "RESTful Web API"。"-ful" 字尾强调它们的设计完全符合 REST 论文里的建议内容。
资源 RESOURCE
在 REST 中的资源 (Resource) 代表整个网络上的资源。网络上提供了各式各样的资源,而网络上的资源由 URI (统一资源标识符,Uniform Resource Identifier) 来提供。
回想,你如何连上我的 博客,你可能通过浏览器直接输入 www.cnblogs.com/shanyou 此域名来到达首页,也能用书签或网络上的链接,经点击后来连上我的博客。然后,你想看这一篇名为「REST 入门介绍」的文章,所以以你接下去点击这文章的标题连结,接去下阅读。我们简易了解一下整个流程:
- 通过URL ( http://www.cnblogs.com/shanyou ) , Client 向 http://www.cnblogs.com/shanyou 发出请求
- www.cnblogs.com/shanyou 收到请求,回应首页给 Client
- Client 又点击 REST 文章连结 (假设是 http://www.cnblogs.com/shanyou/archive/2011/06/30/2095018.html) 向 http://www.cnblogs.com/shanyou发出archive/2011/06/30/2095018.html 此篇文章的请求
- www.cnblogs.com/shanyou 收到请求,响应 REST 文章内容给 Client
Client 的通过 URI 来获取资源的具体象征 (Representational)。Client 取得这些具体象征使这些应用程序转变其状态 (以 浏览器而言,取得 HTML、CSS、JavaScript … 来生成界面),随着不断取得资源的具体象征, Client 端不断地改变其状态,这样不断的反复 (iterations ) 过程就是所谓的 Representational State Transfer。
使用 WEB 标准
上述是最接近日常的范例,这些行为在 HTTP 规范中称之为 GET,也就是通过URL 来 GET 我想要的资源。另一常用的例子是填写表单,例如,登入表单,我想进行登入动作,就必须先发送账号与密码给某一资源,此资源会验证你所传送的数据是否正确,再进行后续动作。我们发送信息给资源的行为在 HTTP 规范中称之为 POST。
在 HTTP/1.1 RFC 2616第 5.1.1 Method 一节定义了八大类 HTTP 方法,除了我们常用的 GET 与 POST 之外,在 REST 中常用的还有 PUT 与 DELETE。此 GET, POST, PUT, DELETE 正好可以对应我们 CRUD (Create, Read, Update, Delete) 四种数据操作。
HTTP Method 与 CURD 数据处理操作对应 |
||
HTTP方法 |
数据处理 |
说明 |
POST |
Create |
新增一个没有id的资源 |
GET |
Read |
取得一个资源 |
PUT |
Update |
更新一个资源。或新增一个含 id 资源(如果 id 不存在) |
DELETE |
Delete |
删除一个资源 |
RESTFUL WEB SERVICE
RESTful Web Service (又称 RESTful Web API) 是一个使用 HTTP 并符合 REST 原则的 Web 服务。我们知道,通过 URL 可以传送 GET 请求,在 表单指定 method="GET|POST" 来送出请求。但我们要处理 PUT 或 DELETE 的请求呢?通过 RESTful 我们可以简单 URI 来定义资源并和 HTTP 方法配合使用。
Resource 与 HTTP 方法的对应 |
|||||
资源 |
资源说明 |
GET |
PUT |
POST |
DELETE |
http://www.cnblogs.com/Products/ |
Products是一组资源集合 |
列出 该组资源集合中每个资源的详细信息 |
更新 当前整组资源 |
新增 或附加一个新资源。该操作传回新资源的URL |
删除 整组资源 |
http://www.cnblogs.com/Products/1 |
Products/1是单个资源 |
取得 指定的资源的详细信息 |
更新 或新增指定的资源 |
新增 或附加一个新元素 |
删除 指定的元素 |
以上表格有没有很像我们一般在对数据库表格的操作顺序,进入一个 Table 的数据首页 (通常是列表),此页面会有「新增、更新、删除、详细」等连结,你想进行什么操作,就点那一个连结。
在 RESTful 每个资源有自己独立的 URI, Client 从资源集合或单个资源开始进入,不管是资源集合或单个资源,我们都能与 HTTP 方法配合使用,例如,GET 下载,PUT 更新,POST 新增,DELETE 删除。
ASP.NET Web API 是一个框架(framework),能让你在 .NET Framwork 之上架设 HTTP 服务 (HTTP Services)。ASP.NET Web API 是 .NET Framework 上构建RESTful 应用程序的理想平台。
在 Julie Lerman's 的 How I see Web API 一文中,用了一张图来简明说明 Web API:
An Introduction to ASP.NET Web API
GET操作是安全的。所谓安全是指不管进行多少次操作,资源的状态都不会改变。比如我用GET浏览文章,不管浏览多少次,那篇文章还在那,没有变化。当然,你可能说每浏览一次文章,文章的浏览数就加一,这不也改变了资源的状态么?这并不矛盾,因为这个改变不是GET操作引起的,而是用户自己设定的服务端逻辑造成的。
PUT,DELETE操作是幂等的。所谓幂等是指不管进行多少次操作,结果都一样。比如我用PUT修改一篇文章,然后在做同样的操作,每次操作后的结果并没有不同,DELETE也是一样。顺便说一句,因为GET操作是安全的,所以它自然也是幂等的。
POST操作既不是安全的,也不是幂等的,比如常见的POST重复加载问题:当我们多次发出同样的POST请求后,其结果是创建出了若干的资源。
安全和幂等的意义在于:当操作没有达到预期的目标时,我们可以不停的重试,而不会对资源产生副作用。从这个意义上说,POST操作往往是有害的,但很多时候我们还是不得不使用它。
还有一点需要注意的就是,创建操作可以使用POST,也可以使用PUT,区别在于POST 是作用在一个集合资源之上的(/uri),而PUT操作是作用在一个具体资源之上的(/uri/xxx),再通俗点说,如果URL可以在客户端确定,那么就使用PUT,如果是在服务端确定,那么就使用POST,比如说很多资源使用数据库自增主键作为标识信息,而创建的资源的标识信息到底是什么只能由服务端提供,这个时候就必须使用POST。
关于GET POST 的混淆
先说相同点,只有了解了相同点之后才能理解为什么会发生混淆。两者都能向服务器发送数据,提交的“内容”[注1]的格式相同,都是var_1=value_1&var_2=value_2&....get 和 post 区别如字面,一个是get(获取),一个是post(发送)。get用来告诉服务器需要获取哪些内容(uri+query),向静态页面(uri)请求则直接返回文件内容给浏览器,向一个动态页面请求时可以提供查询参数(query)以获得相应内容。post用来向服务器提交内容,主要是为了提交,而不是为了请求内容,就是说post的初衷并不要求服务器返回内容[注2],只是提交内容让服务器处理(主要是存储或者处理之后再存储)。get和post出现混淆是因为对提交的数据处理方法的滥用造成的,数据是无辜的。
混淆之一: 将get提交的用来查询的字段当作是存储数据存入了服务器端文件或者数据库。然后就误以为get是用来提交用于存储的数据的。
混淆之二: 编写脚本在服务器端通过处理post提交的数据并返回内容。只要有数据,就能用来进行判断,脚本怎写是程序员的事,而不在乎数据来源的形式(post、get,或者是自己预设值的常量)。这点功能上确实没问题,只是背离的其初始目的而已。
由于都是要传送数据,且数据格式相同(即使数据格式不同,只要能提取出相应数据)。使用的时候难免出现张冠李戴,将get数据用来存储、将post数据用来检索返回数据。但是二者还是有区别的(主要是根据其用途而“人为”[注3]造成的),get的长度限制在2048字节(由浏览器和服务器限制的,这是目前IE的数据,曾经是1024字节),很大程度上限制了get用来传递“存储数据”的数据的能力,所以还是老老实实用来做检索吧;post则无此限制(只是HTTP协议规范没有进行大小限制,但受限于服务器的处理能力),因此对于大的数据(一般来说需要存储的数据可能会比较大,比2048字节大)的传递有天然的优势,谁让它是 nature born post 呢。
get提交的数据是放在url里,目的是灵活的向服务其提交检索请求,可以在地址栏随时修改数据以变更需要获取的内容,比如直接修改分页的编号就跳到另外一个分页了(当然也可能是 404)。post提交的数据放在http请求的正文里,目的在于提交数据并用于服务器端的存储,而不允许用户过多的更改相应数据(主要是相对于在url 修改要麻烦很多,url的修改只要点击地址栏输入字符就可以了),除非是专门跑来编辑数据的。
花边:post和get的安全性在传输的层面上区别不大,但是采用url提交数据的get方式容易被人肉眼看到,或者出现在历史纪录里,还是可能被肉眼看到,都是一些本地的问题。