V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
gkiwi
V2EX  ›  问与答

restful 的一个网站设计问题

  •  
  •   gkiwi · 2015-04-23 15:03:28 +08:00 · 5019 次点击
    这是一个创建于 3501 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近想尝试用restful构建新的项目,但是遇到了几个疑问点,求有经验的兄弟来帮忙解解惑.

    1. 我封装了一个restful的接口(api),那么网站html该怎么被请求/渲染呢?

      我设想的是,restful单独启动一个服务,然后用nginx直接映射到template目录,然后通过api请求数据,使用前端模板进行渲染,大家是否这样子?还是有更好的方法?

    2. 在上面1的理解上上我在网上搜了下,发现了这个http://segmentfault.com/q/1010000000187725 ,大意是说刚刚的1中设想比较浪费资源,其建议是抽离出一层用于封装业务逻辑,只不过有些接口单独的提供api,一些接口负责将后端渲染好的html吐给前端.但是这个也有几点疑问:

      1. 这样子需要单独维护api侧和html渲染侧,其实无非是在原来的非restful设计基础上又整理出了api接口,业务量会增加不少,似乎后期维护也会多些体力,我有些现有的代码就是这样子的.
      2. 正如上侧所说,后端渲染的html页面吐给web端,web端不可避免的需要ajax请求,这个时候似乎又需要再封装一些纯吐json数据的接口,特别是在需要授权的时候,此处是通过cookie有状态的ajax请求,其与restful的无状态有概念上的一些冲突,这个ajax改怎么处理才合适?
    3. 如果大家知道开源restful项目,还请给予推荐,让俺学习学习,谢谢(以python的最佳).

    29 条回复    2015-04-24 14:39:53 +08:00
    scys
        1
    scys  
       2015-04-23 15:10:31 +08:00   ❤️ 1
    提供API的接口,尽量不提供任何HTML页面服务。
    分开两种服务的负载。
    learnshare
        2
    learnshare  
       2015-04-23 15:14:29 +08:00   ❤️ 1
    RESTFul 是 API,只有数据接口,跟页面毫无关系。

    页面可以是静态文件(jQuery/Angular.js),然后在 JS 中请求 API 中的数据,并展示到页面中(这种方式和 App 类似,Android/iOS 与 Web 可以共享同一套 API);
    也可以是另一个后端服务,这个后端负责请求 API 并渲染页面(这样就是两个后端了)。

    http://www.django-rest-framework.org/ 是一个 django 的框架,可以用来做 RESTful API。其中也附带了一个调试 API 的 Web 工具,可以参考。
    gkiwi
        3
    gkiwi  
    OP
       2015-04-23 15:18:28 +08:00
    @scys 谢谢.不过还是有点小问题想问下:

    假设restful服务称为A,html页面我单独启一个服务(比如B)进行处理,那渲染呢?是
    1. 我在B端就直接调用A服务进行渲染,然后再吐给用户
    2. 还是直接将html文件扔给用户,然后在浏览器端通过js进行前端渲染?

    这两个哪个比较好?

    按我的理解,似乎用2比较方便,但是如此的话,登陆怎么办?因为restful没状态,我该怎么保存用户的认证呢?把认证后的token存在localStorage或者cookie中么?
    求解惑:)
    learnshare
        4
    learnshare  
       2015-04-23 15:22:45 +08:00   ❤️ 1
    RESTful 的 API 可以通过 token 的方式完成用户认证,就是每个登录过的用户在请求时都通过这个 token 来辨认。

    >单独维护api侧和html渲染侧
    是否使用 RESTful 方式,甚至是后端 API 方式,要看具体的应用场景。RESTful 只能提供访问数据库的一个个 API,使 Web/App 端可以与后端彻底分离,让第二个人单独开发都可以。如果 Web 的渲染也用后端做,那就需要两个后端(API 和渲染)来支持了。

    >后端渲染的html页面吐给web端,web端不可避免的需要ajax请求
    好像没有啥关系
    gkiwi
        5
    gkiwi  
    OP
       2015-04-23 15:24:45 +08:00
    @learnshare 谢谢.

    麻烦请参考下第三条的回复, 如果再起个服务进行页面渲染的的话,那么权限认证该怎么处理好呢?因为html端显然是通过cookie存储比较方便,那么这个服务B,请求restful服务A的时候,用什么做认证呢?像我上面说的将token存在cookie里面是否靠谱?
    learnshare
        6
    learnshare  
       2015-04-23 15:27:33 +08:00   ❤️ 1
    @gkiwi 再展开说说 token 的认证方式。

    1. 所有要求登录后才能访问的 API 都必须携带有效的 token 来访问,否则就要求用户去登录;
    2. 登录 API 可以 POST api_url/login {user, pswd},然后返回 {token},可以存到 cookie/localStorage 等位置。

    token 的方式该如何控制安全性,可以自己多思考吧。
    gkiwi
        7
    gkiwi  
    OP
       2015-04-23 15:29:58 +08:00
    @learnshare 为什么总比你慢半拍!!!

    大概了解了,确实再把html渲染交给后端,似乎就浪费了前端分离的优势了.知道该怎么做了,非常感谢:)

    多加个问题,token每次由用户端发送,特别是某些GET请求时候,安全性有啥办法处理么?https?
    gkiwi
        8
    gkiwi  
    OP
       2015-04-23 15:30:56 +08:00
    @learnshare 又慢你半拍,token之前有看过,我再去找找安全性的保证相关的.

    非常感谢:)
    learnshare
        9
    learnshare  
       2015-04-23 15:35:41 +08:00   ❤️ 1
    @gkiwi 使用 RESTful 来写 API 之后,前端页面有两种方式来做:

    1. 用另一个后端调用 API 来渲染;
    2. 纯前端渲染,Ajax 等方式调用 API。

    在某种程度上说,方式 1 不符合后端 API 化的目的(都已经写成 API 了,还要渲染页面干嘛)。不过后端渲染的方式也有其优势(性能高一些等);
    方式 2 就是将前端写成一个 WebApp,和写一个 Android/iOS App 类似的方式,通过 Ajax 等手段来访问 API。这种方式彻底分离了前后端,可以交给不同的人来做,相互之间都不用了解实现细节,只通过 API 文档沟通就可以了。

    当然,也有一些前后端同时做页面渲染的技术,门槛高,没玩过。
    learnshare
        10
    learnshare  
       2015-04-23 15:36:57 +08:00
    @gkiwi 慢半拍是因为我在补充自己,而不是回复你的问题 √
    gkiwi
        11
    gkiwi  
    OP
       2015-04-23 15:45:56 +08:00
    @learnshare 确实如你所说的,似乎再用后端来渲染html不大合适,之前老想着认证这块,所以就痛哭了..

    前后端渲染我用后端jinja2+前端vuejs做过一个web离线订单的处理,因为考虑纯离线的web操作,只能用前端框架做数据绑定和渲染,不过最后前端性能出了问题...
    gkiwi
        12
    gkiwi  
    OP
       2015-04-23 15:46:25 +08:00
    @learnshare 一起学习进步:)
    caixiexin
        13
    caixiexin  
       2015-04-23 15:51:04 +08:00
    感觉像是在纠结是不是完全遵守RESTful设计网站,我刚接触的时候也有这种纠结 = =
    用前端html模板渲染的方式还是后端渲染再吐给用户的方式?
    看你的应用场景吧,我记得前端渲染一般都是单页型应用(Gmail,笔记网页版什么的),前端技术好的话可以做到很多酷炫的webapp,用上前端mvc框架还能做出兼容各种设备的响应试应用。但是有几个缺点:页面渲染慢,项目刚开始前端工作量比后端大,SEO支持不好什么的。传统后端渲染的优缺点就跟它相反了。业务复杂的站点肯定根据实际需求两种都会用到的。
    个人觉得RESTful只是种http的资源设计风格,严格遵守的话,会束手束脚的。个人学习的话,多做些尝试或许能更明白一些。
    我也半桶水,希望没说错:(
    caixiexin
        14
    caixiexin  
       2015-04-23 16:07:10 +08:00
    还有登录认证问题,我觉得就是因为要保证RESTful资源的无状态,才会有token的存在啊,因为它没有任何状态数据,只是个票据而已。
    RESTful的安全控制,具体可以参考下目前各大开放平台使用的OAuth2.0方式。
    clino
        15
    clino  
       2015-04-23 16:12:27 +08:00
    我现在用uliweb+avalonjs写web应用的时候都是用这种方式,后端大部分只是提供api, javascript 的代码比后端的多不少

    问题1,用avalonjs这种mvvm类型的刷新从api获取到的内容的时候只要管更新数据就可以了,用这类框架开发效率较高

    问题2.2,对于我这里的情况,api接口和其他的接口没什么差别,一样可以用session来鉴别用户,当然不用这个用其他的机制也可以
    gkiwi
        16
    gkiwi  
    OP
       2015-04-23 16:12:59 +08:00
    @caixiexin 不能赞同更多.

    我也是最近有些空闲,自己做个新项目,就想用restful练练手,学习下restful和angularjs.
    不过每次看到angularjs.cn网站我就有些蛋疼,毕竟主要内容需要0.5-1秒后才出现...
    gkiwi
        17
    gkiwi  
    OP
       2015-04-23 16:23:28 +08:00
    @clino 其实session和cookie并无太大区别,但是用于restful就变成有状态认证了,和restful所谓的无状态是概念冲突.当然啦,正如@caixiexin 所说,这个就是是否遵守restful协议的问题...
    learnshare
        18
    learnshare  
       2015-04-23 16:44:40 +08:00   ❤️ 1
    @caixiexin 响应试 -> 响应式 和 MVC 没关系,甚至可以跟 JS 没关系
    clino
        19
    clino  
       2015-04-23 16:59:20 +08:00
    @gkiwi 貌似是的,不过我上面说了"用其他的机制也可以"
    caixiexin
        20
    caixiexin  
       2015-04-23 17:17:14 +08:00
    @learnshare 啊。。抱歉,确实说错了,后端做多了,前端苦手,见谅:)
    mytharcher
        21
    mytharcher  
       2015-04-23 17:25:01 +08:00
    题主所说的需求其实最主要是在响应的时候根据请求头中的 accept 字段来进行判断输出就好了。这是 HTTP 协议的标准方法,比如 express 框架 4.0+ 就支持了: http://expressjs.com/4x/api.html#res.format

    举个例子,对同一个资源的 GET 访问: http://yourhost.com/employee ,如果在请求头里的 accept 指明了 application/json 那么就返回 JSON 数据,否则浏览器默认最大概率是 text/html 这样就可以判断返回渲染好的网页。

    多维度(method/accept/content-type等)的区分控制才是 RESTful 的正道。至于上面说的用 token 保持状态,其实和 cookie 区别不大,对浏览器来说还要自己维护过期时间,所以不如直接 token 放 cookie 里。
    gkiwi
        22
    gkiwi  
    OP
       2015-04-23 18:56:18 +08:00
    @mytharcher 学习了,利用accept作区分确实是一种很好地思路.
    不过我的起始困惑是:在html页面渲染上,由前端渲染还是后端渲染,两种情况下的授权机制该怎么处理才比较合适的问题.


    token若是存在cookie里面,给我的感觉和session没啥区别了,都是本地拿着一个认证key.
    觉得token存在localStorage似乎更好些,因为存在cookie里面就不叫无状态了...

    restful设计思路目前来看一个好处就是不需要ios/android/wp等各平台自家的应用维护cookie.而且token的周期应该由服务器来维护,而不是浏览器.
    mytharcher
        23
    mytharcher  
       2015-04-23 19:50:30 +08:00
    前端渲染和后端渲染主要看需求,比如需要 SEO 那就后端渲染,否则现在大规模的 Angular 等框架全是在前端渲染的。而且这跟授权机制好像没有太大的联系,这类非内容的文件,基本就是和 js/css 一样归为任何人可见 assets 的。

    至于 token 存在 cookie 里,和你存在 localStorage 里唯一的区别就是过期时间,如果你后端直接忽略掉 cookie 内容,那就变成无状态的了。有自动管理过期时间的 cookie,那就没必要折腾一套东西来专门处理,而且反正你都要放在 header 里。
    armoni
        24
    armoni  
       2015-04-23 20:57:13 +08:00
    用nodeJS渲染吧,nodejs里调用rest api获取json,渲染到HTML,就是angular写的头疼
    armoni
        25
    armoni  
       2015-04-23 20:58:59 +08:00
    @gkiwi 存在localStorage里
    gkiwi
        26
    gkiwi  
    OP
       2015-04-23 22:37:44 +08:00
    @mytharcher

    其实使用angularjs,在SEO这块有种解决方案,就是在判断出是搜索引擎时候,专门吐出一些不带样式的网页,不过从pagerank算法来讲,这个显然是不太好,而且据说有一定几率会被搜索引擎识别为作弊而封掉.

    token放在cookie不读取,你这块的意思是每次想后端api请求时候,现在浏览器端读取token然后作为参数传到后台么?如果是这个,那确实是无状态的了,哈哈~
    不过有几个缺点:
    1. 每次cookie都被请求带着,占用带宽,特别是有很多同域图片时候,每次请求都带着cookie就有点过分了,这个也是设计restful的一个原因(?优势?).
    2. 后端做token时间管理是基本上必不可少的,因为还得考虑安卓/IOS/WP之类的app端.可以参照这个帖子:/t/148426 .因为在每个平台的app都维护一套时间管理显然成本更高.

    当然啦,目前我要做的项目只有web端,token放哪里都可以了.目前尽量按照restful的标准来就是纯为练练手:)
    gkiwi
        27
    gkiwi  
    OP
       2015-04-23 22:38:45 +08:00
    @armoni 每次想去学习angularjs都头疼...localStorage最好不过:)
    mytharcher
        28
    mytharcher  
       2015-04-24 09:05:26 +08:00   ❤️ 1
    需要用前端 history API 且 SEO 这事其实主要是改造服务端,添加 rewrite 规则以及里用 accept 吐不同类型的结果才是正道。至于 Google 愿不愿意去解析执行 JS 后再索引那是另一回事。

    服务端忽略 cookie 这里更正一下,这个说法其实我说的不准确,后面补充说。但是 token 放 cookie 里是没有问题的,如果你不用 cookie,那么无论如何也要找地方来放,放 query 里肯定是不合适,所以一般是用 header 里的字段,比如 Authorization,而且图片等静态资源一般通过 CDN 来区别域名,所以不存在占用带宽的区别。除了 cookie 的 HTTP 头浏览器都不会在本地自动保存并过期失效,那么有现成的东西就没必要去另外实现一套机制。即使在其他客户端(原生),自己实现从头里取另一个字段保存并设置有效时间,和取 cookie 没有本质的区别。

    补充说 cookie 到服务端的情况,服务端拿到请求头以后,无非也就是一个字段,至于 session 是如何实现的那是另一码事,可以放程序内存(单机),也可以放数据库(多机)。而且就算号称是无状态的,没有 session 怎样验证 token 的有效期和合法性?实际上我在另一个关于 RESTful 的帖子( /t/118049 )里就说过关于用户获取授权的请求问题 ,登入其实就是一个 POST /session 的请求,用以在服务端的 session 记录中新增一个项目,之后用以验证查询。所以无状态之说,现在想来根本不现实,除非客户端和服务端都永久保存 session 的 token,就像 ssh-key 一样。

    至于你提到的 /t/148426 帖子里最后大家的结论其实一样 token 和 session 根本不是一个层面的事情。
    gkiwi
        29
    gkiwi  
    OP
       2015-04-24 14:39:53 +08:00
    @mytharcher

    关于SEO我俩应该没啥分期.

    我觉得你可能忽略了客户端单独维护cookie的成本~

    对于token的每次请求存哪里(cookie,header,每次查询时候待在参数里面),网上各种例子都有,比如将token放在每次查询到串里:
    http://stackoverflow.com/questions/25327476/implementing-an-restful-api-authentication-using-tokens-yii
    这个app端不需要任何的时间管理处理,只要在第一次登陆时候,服务器返回一个token数据,开发人员将其存在本地存储即可.
    至于你后面说的,"没有 session 怎样验证 token 的有效期和合法性"这个建议你看看这个:
    https://github.com/miguelgrinberg/REST-auth/blob/master/api.py
    无状态是指的client端:)
    token和session的区别异同,
    建议看看这个:
    https://auth0.com/blog/2014/01/27/ten-things-you-should-know-about-tokens-and-cookies/
    至于是不是一个层面,这个得看所指的深度了,看清本质就好了,个人有个人的看法,无法统一.

    谢谢一起扯皮了这么久,自己对这块的理解也有新的认识:)
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1142 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 18:31 · PVG 02:31 · LAX 10:31 · JFK 13:31
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.