回答朋友关于REST的一些疑问

29 views
Skip to first unread message

dlee

unread,
Apr 7, 2008, 1:45:29 AM4/7/08
to REST实战
今天在MSN上回答了朋友关于REST的一些疑问。感觉朋友的疑问很有代表性,征得他的同意后发在这里。

zhao...@hotmail.com: hi
李锟(dlee): hi
zhao...@hotmail.com: 好久没见,可好?
李锟(dlee): 还好
李锟(dlee): 你现在在哪里啊?
zhao...@hotmail.com: 呵呵,我还是老样子啊。有个关于restful的问题想不明白,就想起你来了。
李锟(dlee): 呵呵,可以来我们的讨论组讨论
zhao...@hotmail.com: 应该没那么复杂,就是一个简单的问题,你看这里:
zhao...@hotmail.com: http://erlang-china.org/misc/restful_erlang_yaws.html
zhao...@hotmail.com: 看我后面的comment就行了。
zhao...@hotmail.com: 主要是对restful的理念还不是很清晰。
zhao...@hotmail.com: 我看到webdav自己扩展了很多http的方法,这是restful所鼓励的么?
李锟(dlee): 这个问题很有代表性,是大多数人对REST心存疑虑的原因
zhao...@hotmail.com: 恩,我想,可能是我在哪里没有理解透彻
李锟(dlee): 答案是,如果需要更多的操作,定义一个新的资源
李锟(dlee): 这里主要的问题是,大多数人不理解资源是抽象的
zhao...@hotmail.com: 哦?可是。。。问题在于,这样的话,URL的数量岂不是会成倍的增加?
李锟(dlee): 大多数人把资源看作是一些很具体的东西,例如服务器端的一个文件、数据库中的一条记录。
李锟(dlee): 没有关系啊,URL数量成倍增加有什么问题?
zhao...@hotmail.com: 恩。看来就是在这里理解有问题了。我之前认为RESTful将资源定义为URI是为了规约URI,通过
引入methods来解决自定义act参数的问题。
李锟(dlee): URI+4种HTTP方法本来就是设计用来做这个事情的
zhao...@hotmail.com: 好像见过你提到comet和restful是有冲突的?具体怎么讲?
李锟(dlee): 当然可以引入自定义的method,WebDAV就是这样干的,不过这种做法不推荐。
李锟(dlee): 对,是有冲突的
zhao...@hotmail.com: 是的哦,自定义的method在设备的通过性上违背了restful的原则,所以,我也很存疑。
李锟(dlee): comet的典型实现,包括Dojo的那个什么协议都是这样做的
李锟(dlee): 客户端通过动态生成的script标签请求服务器的一个用不结束的代码流
李锟(dlee): 这个代码流中有js脚本,通过这些脚本来传递数据
李锟(dlee): 这样做违反了REST
zhao...@hotmail.com: 违背了哪一条?
李锟(dlee): 没有人说你绝对不应该违反REST,REST也不是五台山上的清规戒律。只是告诉你如果你违反了REST,你会付出代价。
zhao...@hotmail.com: 是不是rest暗示并非针对有连接的应用?
李锟(dlee): 如果你觉得这样的代价可以承受,那就无所谓了
李锟(dlee): 违反REST是因为违反了操作语义的可见性
李锟(dlee): 操作的语义不应该由消息体来传达
李锟(dlee): 而应该完全放在头信息字段中
李锟(dlee): 这样中间组件才能够以最有效的方式实现缓存和安全审计。
李锟(dlee): 违反了操作语义的可见性,就打破了REST的统一接口,会对应用的可伸缩性造成严重影响。
李锟(dlee): 这种方式,客户端很难实现有效的缓存。
zhao...@hotmail.com: 但是对于像comet这种在无连接的http上实现有连接的应用模式,因为browser不保持连接,
似乎是很难在rest框架内做到语义的可见性。
李锟(dlee): 所以Comet是有代价的,如果服务器端没有相应的支持,并发一大就会耗费掉服务器端的所有资源。
李锟(dlee): Jetty解决这个问题是通过Java NIO的无阻塞连接实现的
李锟(dlee): Tomcat也有类似的支持
zhao...@hotmail.com: 对于这个问题,试想,如果换成老的xhr定时刷新,是否会更加符合rest原则呢?
李锟(dlee): 那样更符合REST原则,但是实时性就差很多了。
李锟(dlee): 无连接就是为了得到最大的可伸缩性
李锟(dlee): 服务器端无状态也是为了得到最大的可伸缩性
zhao...@hotmail.com: 我有一个疑问,比如 GET /chat/room/update 这个就是不断刷新的动作,这个语
义,我感觉可见性还是没有表达出来呢。因为,这里隐含了 who ,这个 who 可能是通过 cookie 或什么别的来传递的。这个 who 某种
意义上就是一个状态。
zhao...@hotmail.com: 从 rest 的原则来设计,这样的有状态的东西,要如何转换为无状态的呢?
李锟(dlee): Comet通过GET请求还有可能改变服务器端资源的状态,这样做是不对的。GET不应该改变资源的状态。
李锟(dlee): cookie对于REST应用来说应该完全弃用。
zhao...@hotmail.com: 是否这样更加符合REST?

POST /chat/room/update

?who=1234
李锟(dlee): 或者这样说,cookie不应该作为客户端与服务器端传递资源状态的手段,因为它不适合做这件事情
李锟(dlee): cookie只应该用来在客户端保存客户端自己的状态,服务器端应该完全不处理cookie
李锟(dlee): cookie应该被当作客户端离线存储的一种手段
李锟(dlee): POST /chat/room/1234
李锟(dlee): 这样就可以了
李锟(dlee): who这个信息应该出现在URL中
zhao...@hotmail.com: 如果这样的话,似乎有个伪造url的风险
李锟(dlee): 不放在URL中就不会被伪造了吗?
李锟(dlee): 伪造有什么危害?
zhao...@hotmail.com: 对聊天室来说,伪造就有冒充其他人说话的问题。
李锟(dlee): 那是通过HTTP身份认证来解决的
李锟(dlee): HTTP 1.1内建的机制
李锟(dlee): 还支持引入第三方的认证算法
zhao...@hotmail.com: http身份认证对于游客是一个问题啊
李锟(dlee): 很简单,游客不需要认证就可以发言,但是要以dlee的名义发言,必须通过身份认证
zhao...@hotmail.com: 恩,是我没有说清楚。这里的身份,是某一个客户端,不是某一个用户的意思。在一个chat的会话中,关
键是要“将信息送给确定的人”,可能两个人都是游客,但,发送给A的就不能发送给B。
李锟(dlee): 某个客户端的身份认证也一样可以用HTTP身份认证机制来实现
zhao...@hotmail.com: 这里其实就是一个token,目前的http设施之中,cookie似乎是这个token的最好存放地
点。
zhao...@hotmail.com: 我所认为的http身份认证是发起一个http验证请求,此时用户的浏览器会探出一个输入用户名和密码
的框,我们说的是不是同一个东西?
zhao...@hotmail.com: 作者:kk

比如:聊天室、竞价拍卖、股票交易……,

这些已经脱离了’资源’这个范畴了,算soa方面了,需要人肉写交互代码吧



你觉得这个回应怎么样?我觉得这类应用,rest应该也能适用才是吧。
zhao...@hotmail.com: 呵呵,浪费了你很多时间。我先去吃饭了,回头再聊。
李锟(dlee): 刚才去吃饭了
李锟(dlee): 就是这个HTTP身份认证,不过也可以自己来实现
李锟(dlee): HTTP身份认证是针对一个realm的,就是服务器端一组资源
zhao...@hotmail.com: 这个身份认证还能让它不弹出一个对话么?
李锟(dlee): cookie是针对一个domain的,对应服务器端的所有资源,范围比realm大
李锟(dlee): 《Ajax模式与最佳实践》中有介绍,我回去再帮你看看
李锟(dlee): 资源是抽象的,跟社会主义初级阶段一样,什么都可以塞进去。
李锟(dlee): 它就像如来的手掌一样
李锟(dlee): 开个玩笑,呵呵
zhao...@hotmail.com: 哈哈。。。
zhao...@hotmail.com: 看来用rest需要在url上狠做文章
李锟(dlee): RESTful Web Services里面讲的挺清楚的,建议参考一下
李锟(dlee): URL用来携带地址信息,就是who的信息,HTTP method用来携带操作语义。
zhao...@hotmail.com: 恩,好的,我回去参考下。还是回那个问题本身,rest很强调无状态,那么一个在本质上就是有状态的应
用在rest框架内,是否能够得到妥善的解决呢?这个问题是否有人回答过了?
李锟(dlee): 无状态指的是会话的状态,不是资源的状态。
李锟(dlee): 我以前写过Fielding论文导读,澄清过这个问题。
李锟(dlee): 会话的状态应该完全在客户端
李锟(dlee): 每个请求应该携带完成该请求必须的所有会话状态
zhao...@hotmail.com: 照这么说,session之类的服务端状态机制也是为rest所反对的吧。
李锟(dlee): 对的,其实真正的REST应用完全不用session
李锟(dlee): Rails 2.0做了一个折中的设计,就是session数据默认保存在客户端的cookie中
李锟(dlee): 这样服务器可以不必保存session数据,提高了服务器的可伸缩性
zhao...@hotmail.com: 恩,但是在具体应用之中,状态这个东西在服务端是确实存在的。比如,购物车,如果完全放在客户端,似乎
也能工作。但至少,服务端还是需要保存用户在结帐之前已经买了什么东西。这种状态,在rest中是怎么映射的呢?
zhao...@hotmail.com: 是否也将其弄成某种资源来处理?
李锟(dlee): 开始的时候说到的WebDAV的做法,是完全符合REST的做法,因为REST的统一接口并没有限制每个接口只能有几个方
法。Fielding本人也明确肯定WebDAV的做法没有问题。
zhao...@hotmail.com: 哦?不是说webdav自己加入的n多自定义的http方法,违反了rest的原则么?
李锟(dlee): 不过WebDAV的统一接口,超越了HTTP 1.1定义的统一接口,在很多地方可能无法实现。例如很多语言的HTTP库只支持标
准的HTTP方法。它也是一种统一接口,但是它没有HTTP 1.1的统一接口那么通用。
李锟(dlee): 主要是实现难度上的考虑,不是说webDAV违反了REST的原则
zhao...@hotmail.com: 哦,原来是这个意义上的问题。
李锟(dlee): 保存用户在结账之前买了什么东西,这是资源的状态,可以保存在服务器
李锟(dlee): 保存在服务器的好处是用户下次在另一台机器上登录,仍然可以看到以前选择的东西。
李锟(dlee): 不过这个状态是资源状态,不是会话状态
zhao...@hotmail.com: 也就是说,购物车是一个资源,它有自己的状态。在设计url的时候可能是这样

添加一个东西到购物车: PUT /mall/who/cart/ 在 body 部分则放的是 what
zhao...@hotmail.com: 这个理解有问题么?
李锟(dlee): 没有问题,what就是资源的一个表述
李锟(dlee): 消息体里面携带的是资源的表述
李锟(dlee): 地址信息和操作语义在URL和HTTP方法中,其他的HTTP头信息字段可以携带一些控制元数据,例如指示中间的缓存组件不要缓存
这个请求。
zhao...@hotmail.com: 我这么理解:http head 中 url 是 “什么东西”,这里是“谁的购物车”;method
是做什么,这里是“新增”;http body 中是“参数”,这里是“哪一个商品”(可能是另一个资源(商品)的描述符号)以及“数量”。
zhao...@hotmail.com: 可能是我自己的习惯问题,总感觉把who放在url里面有点不妥。这个可能需要慢慢调整过来。
李锟(dlee): URL中不是“什么东西”,而是who一类的地址信息,代表了服务器端某类资源的一个范围,具体要保存什么内容,放在body里

李锟(dlee): body里面不是参数,那样说容易让人想到RPC,body里面是资源的表述
李锟(dlee): RESTful Web Services这本书的前三章讲的一个很重要的内容就是REST和RPC的本质区别在哪里。
zhao...@hotmail.com: restful webservices 这本书看来很重要啊。哪里有?
李锟(dlee): 讨论组的文件列表里面
李锟(dlee): https://groups.google.com/group/rest_in_action
zhao...@hotmail.com: 恩。俺去下来看看。

Daniel Lv

unread,
Apr 7, 2008, 1:54:27 AM4/7/08
to rest_in...@googlegroups.com
能跟dlee老大直接沟通,真幸福~

2008/4/7 dlee <dle...@gmail.com>:
Reply all
Reply to author
Forward
0 new messages