2

说说REST

 2 years ago
source link: https://limboy.me/posts/rest/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

REST 究竟是什么东东

REST(Representational State Transfer)是 Roy Fielding 在他的博士论文中提出来的。他也是 HTTP 协议的制定者之一。REST 是一种针对网络应用的设计和开发方式,可以降低开发的复杂性,提高系统的可伸缩性。

REST 的特性

C/S 架构

客户端主动向服务端发起请求,服务端收到请求后,返回格式化的结果。

每个请求必须包含服务端所需的所有信息,不要指望从服务端"借"点数据。

如果因为业务需要,要新添加几个资源,可以横向扩展,而不需要改变原来的结构。

统一请求类型

GET/POST/PUT/DELETE,实际中以 GET 和 POST 用的最多。

服务端要提供资源供客户端调用,每个资源都有独立的 URL。

使用标准的 http 请求,各个语言几乎都支持,所以由丰富的客户端。

方便添加中间层

如代理/集群/缓存等等,对客户端而言它们是透明的。

不牵扯具体的业务逻辑,而且格式化的数据很容易解析

以 twitter 为例(请自动切换到翻|墙模式)

获取信息(GET)

如果要获得某条 tweet 的信息,直接访问 api 即可,如 http://api.twitter.com/1/statuses/show/3657615682838528.json,将会返回如下结果

{
    place: null
    geo: null
    // ...
    created_at: "Sun Nov 14 03:56:58 +0000 2010"
    in_reply_to_status_id_str: null

    user: {
        profile_image_url: http://a2.twimg.com/profile_images/259632038/DuanziLogoBig_normal.jpg
        // ...
        description: "官网:www.JokeCook.com | When that happens.当下那些事儿 | 欢迎回复@duanzi 投稿。"
    }
    truncated: false
    id: 3657615682838528
    in_reply_to_user_id_str: null
    text: "Via @ruoxiaosu: 有时候吧,取消对一个人的关注,...via琦殿"
}

省略了部分结果,可以看到是一个包含了很多信息的 json,想怎样展现那就是客户端的事情了。

提交信息(POST)

这个就要复杂一点了,因为涉及到用户验证,前面说过了,REST 是无状态的。也就是说,服务端不知道你到底有没有登录,除非出示证件。是的,每次请求都得出示。服务端验证通过后,查询到用户 id,保存 POST 数据,返回提交结果。

POST /1/statuses/update.json
HOST api.twitter.com

status=blahblah...&oauth_consumer_key=GDdmIQH6jhtm...&oauth_nonce=oElnnMTQIZvqvlfXM56aB...

可以看到除了 status,还有 oauth_consumer_key 和 oauth_nonce(还有其他 oauth 相关的参数),这些就是用来进行身份验证的,如果验证通过了,tweet 就会被正常发布,同时返回该 tweet 的相关信息。

顺便说说用户验证,一般有三种验证方式:Basic Auth/Digest Auth/OAuth(XAuth),就安全性来说 OAuth 是最高的,用户无须输入密码,但部署起来难度也最大。Basic Auth 安全性最低,部署起来也最方便,用户只需提供用户名和密码即可,但如果第三方记录了这些信息,那就... Digest Auth 的安全性和部署成本介于两者之间。

其他更新内容和删除内容也类似,都是先进行用户验证,再进行权限验证,最后返回执行结果。

REST 的原则

抽象出所有可供调用的资源,越精确越好

如果一个事物可以抽象成资源,那它就是 RESTful,可以通过 URL 进行调用。

为每个资源提供一个 URL,且资源应该是名词而不是动词

如,下面这个 url 是不建议采用的

bq. http://www.twitter.com/getUser/10

应该改为这样

bq. http://www.twitter.com/user/10

将资源分类

Tweets resources
	- status/show/:id
	- status/update
	- status/destroy/:id
	- ...
Timeline resources
	- status/public_timeline
	...
User resources
...

所有 GET 请求都不应该影响数据库内容

GET 顾名思义,就是用来获取某个资源,如果要修改,则应该执行 POST/PUT/DELETE。千万不要因为偷懒,而给 GET 留下后门。

返回结果不一定是单独的内容,可以包含相关链接

有时候,这是一种双输的局面:用户不想要那么多的数据,服务端又多了不必要的运算。只要包含可以获取信息的链接即可。

明确返回格式

如 json/xml/html 等等,不过目前来看 json 基本是主流。

如何使用 REST

REST 不仅仅是一种崭新的架构,它带来的更是一种全新的 Web 开发过程中的思维方式:通过 URL 来设计系统结构。在 REST 中,所有的 URL 都对应着资源,只要 URL 的设计是良好的,那么其呈现的系统结构也就是良好的。这点和 TDD (Test Driven Development)很相似,他是通过测试用例来设计系统的接口,每一个测试用例都表示一系列用户的需求。开发人员不应该一开始就编写功能,而是先细分资源。对资源抽象地越精确,对 REST 的应用来说就更好,这个和传统的 MVC 中基于 Action 的思想差别很大。设计良好的 URL, 不但对于开发人员来说可以更明确的认识系统结构,对使用者来说也方便记忆和识别资源,因为 URL 足够简单和有意义。

REST 对开发者友好。Amazon 和 Ebay 的 service 结果显示:60%的用户使用 REST。提供 REST 服务,开发者可以很容易通过各种语言各种平台来开发一个 app,手机/ipad/网站/cli 等等,这也是 web2.0 的一大特征,想想如果 flickr/twitter/delicious 没有开放简洁易用的 api,其火爆程度肯定大打折扣。

使用 REST 还有一个好处是,可以避免 Controller 直接操作数据。假如是 MVC 模式,Controller 很可能途省事,直接把 ORM 拿过来就开始进行数据操作了,如

<?php
class Controller_Post extends Controller {
	public function actionAdd() {
		if (Validate::check($_POST)) {
			$post = ORM::factory('post');
			$post->title = $_POST['title'];
			$post->content = $_POST['content'];
			//...
			$post->save();
		}
	}
}

如果有一天保存的操作改了,如加了一个 status 字段,那就很糟糕了。

实际使用中,可能会发现不是所有的需求都可以抽象为资源,这时可以混用 MVC/MVVM。尽可能地抽象成资源,对其他需求使用 MVC/MVVM 开发。

目前已经有不少基于/支持 REST 的框架,有兴趣的话不妨尝试一下。也可以看一下这篇文章

  • REST 和 MVC 的关系就好像 Div 和 Table 的关系。在 web 标准没推广前,都是使用 Table 布局,Table 原本是用来做数据展示的,不知是哪一位天才发现对 Table 进行各种改造后,可以用作前端展示,于是就这么流传开了。
  • REST 是一种架构风格,不是标准。但使用了很多标准:http/url/mime 等等。
  • REST 概念从提出到现在已经有 10 年了,越来越趋于成熟。它是为 http 而生的,而 MVC 最开始是用来开发桌面软件的。
  • 如果你的网站有提供 API 的打算,推荐使用 REST 架构,开始可能会麻烦一点,但将来会发现这些付出是值得的。

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK