V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
legendlee
V2EX  ›  程序员

请问,我这样理解 restful 对不对?

  •  
  •   legendlee · 2015-10-02 04:08:11 +08:00 via Android · 5604 次点击
    这是一个创建于 3338 天前的主题,其中的信息可能已经有所发展或是发生改变。
    最近设计了两个小型的前后端交互 api 接口系统,参考了 restful 的标准。但是我读的材料可能不够多,对 rest 理解的有点模糊,想让大家纠正一下。

    目前而言,我理解的 rest 就是两句话: url 里面不允许出现任何动词,只能用来表示寻址。
    并且保证所有能用 url 寻址找到的资源对象都支持同样的动词操作(比如增删改查),不支持的可以返回错误,但绝不能支持额外的方法。

    至于别的,比如是完全用 /分割的 url 还是使用传统带的?和&的 url ,是使用标准的 http get/post ,还是把动词放在 body 里,似乎没什么区别。

    请问这样理解对吗?
    30 条回复    2015-10-06 21:10:37 +08:00
    legendlee
        1
    legendlee  
    OP
       2015-10-02 04:12:33 +08:00 via Android
    另外,我感觉如果按照我这样的理解,那么我们完全有可能设计出一种 dsl 描述语言,把各种资源对象的结构和约束,以及操作的鉴权等描述出来,然后编写一个生成器,把基本的前后端逻辑代码生成出来,至少大部分模块生成出来(和数据库无关的部分)。

    请问这么做现实吗?有没有现有的这样的系统?
    msg7086
        2
    msg7086  
       2015-10-02 04:31:06 +08:00
    不太确定你的理解是否正确,反正我们是肯定得允许额外动词的。

    #1 楼 你说的是 Rails generator 吗
    ryanemax
        3
    ryanemax  
       2015-10-02 08:51:08 +08:00 via Android
    Restful api markup language
    raml.org 官网
    背后支持 angularjs 团队, mule


    raml2html raml 转 html
    RAMLang angular 生成
    Api Design mule 大开源的 ide

    Demo:
    api.anasit.com
    api.anasit.com/doc
    raml.anasit.com
    matsuijurina
        4
    matsuijurina  
       2015-10-02 08:53:07 +08:00
    建议楼主去尝试一下 rails scaffold ,会豁然开朗的。
    ryanemax
        5
    ryanemax  
       2015-10-02 09:13:51 +08:00 via Android
    @ryanemax 后端的生成器也很多,参考 raml.org 的 product 页面,如果没有的可以自己造轮子,用官方提供的 parser ,团队在尝试做 laravel5(基本不用做)和 golang 的 generator
    legendlee
        6
    legendlee  
    OP
       2015-10-02 09:16:21 +08:00 via Android
    @ryanemax 嗯,谢谢,这东西好。有点孤陋寡闻了。最近用 nodejs 搞了个简单的内容管理,里面有些东西就是自己写代码生成的,但是比较简陋。
    xavierskip
        7
    xavierskip  
       2015-10-02 09:51:52 +08:00
    URL 用来定位资源, HTTP 描述操作。
    Lucius
        8
    Lucius  
       2015-10-02 10:09:48 +08:00
    “ RESTful 架构有一些典型的设计误区。
    最常见的一种设计错误,就是 URI 包含动词。因为"资源"表示一种实体,所以应该是名词, URI 不应该有动词,动词应该放在 HTTP 协议中。”

    via: http://www.ruanyifeng.com/blog/2011/09/restful.html
    imzshh
        9
    imzshh  
       2015-10-02 10:35:37 +08:00
    URL 在 REST 风格的 api 里面只是用来定位一个资源,用不用动词,是不是出现 query string 都没问题。其它内容像是如何利用现有的 HTTP 协议表示 CURD 等操作,处理错误、缓存,怎么进行并发控制、身份验证等等,这些约定才是 RESTful 的精髓。
    legendlee
        10
    legendlee  
    OP
       2015-10-02 10:36:36 +08:00 via Android
    @Lucius 好像跟我想的差不多。
    imzshh
        11
    imzshh  
       2015-10-02 10:44:52 +08:00
    @Lucius 这种说法才是对 RESTful 的错误认识,这里说的资源是一个抽象概念,出现动词并不会改变它是一个资源的本质。并且在真正 RESTful 的服务器和客户端的交互中,客户端并不关心 url 的格式是怎样的, url (也就是资源)都应该由服务器(通过类似 html 里的链接的方式)告诉客户端,而不是客户端自行生成。
    Lucius
        12
    Lucius  
       2015-10-02 10:50:19 +08:00
    @imzshh
    你的理解是错误的, RESTful 的基本原则概括成一句话就是

    “ URL 定位资源,用 HTTP 动词( GET,POST,DELETE,DETC )描述操作。”
    imzshh
        13
    imzshh  
       2015-10-02 10:53:39 +08:00
    @Lucius 这句话里有说 URL 里不能出现动词吗?
    Lucius
        14
    Lucius  
       2015-10-02 10:55:43 +08:00
    @imzshh

    如果你认为 URL 里出现动词是合理并且规范的,那么后面半句标准根本就没有意义
    canesten
        15
    canesten  
       2015-10-02 10:57:36 +08:00
    @Lucius
    所以一个合格的 Restful 的站就是按照不同 HTTP 动词对 URL 资源进行增删改查?
    我是觉得只有 GET,POST,DELETE,PUT 好像并不能表达一些复杂的业务。
    还是说 Restful 的设计就一定要避免复杂业务?
    Lucius
        16
    Lucius  
       2015-10-02 11:01:51 +08:00
    @canesten

    我觉得 URL 里出现的应该是实践的 结果 例如 “ products ” 这个名词

    而不是一个过程、动作 例如 “ get-products ”
    imzshh
        17
    imzshh  
       2015-10-02 11:08:40 +08:00
    @Lucius 这么说吧, URL 中不出现动词当然是极好的,但是有时候难免会出现不得不出现动词的情况。传统的带?和&的 URL 在 REST 风格的接口中也是可以出现的,进行查询( query 不是 get )的时候也应该使用。我想要表达的是 URL 怎么设计只是整个 REST 架构风格中很小的一点,不要认为 URL 没有出现动词没有?和&了就 RESTful 了,反之就不是 RESTful 了。
    canesten
        18
    canesten  
       2015-10-02 11:13:02 +08:00
    @Lucius
    所以你说的还是简单业务
    对于增删改查我承认你的看法
    但是其实现实中很多不得不妥协
    因为 HTTP 动词表达不了复杂语义
    就像#17
    @imzshh
    说的一样
    hantsy
        19
    hantsy  
       2015-10-02 11:16:46 +08:00
    @legendlee 参考这里讨论。 http://www.v2ex.com/t/221304

    @ryanemax RAML 从一开始回到了 SOAP 的老路,这是使用 REST 的程序员最不希望看到。记得使用 SOAP 的时候,讨论的一个最基本的问题就是 Contract First 还是 Code First ,基于 SOAP 多于牛毛的各种规范,导致 Contract First 占优势。从技术人员的角度看,大部分都是愿意使用 Code First ,这也是 REST API 很盛行代替 SOAP 的原因。

    RAML 最初也是 Swagger 描述中抽象出来的。 Swagger 初衷是可视 REST API ,我已经在项目已经使用了两年以上 Swagger 。但 Swagger 不支持 REST API Rechardson Model Level3 , 如 HAL 等。 HAL Browser 更简单一些。
    initdrv
        20
    initdrv  
       2015-10-02 11:20:20 +08:00
    看看大牛们的见解,新手 mark 一下!
    imzshh
        21
    imzshh  
       2015-10-02 11:23:18 +08:00
    @Lucius 阮大的文章当成科普文看看就行了,当成教科书来学习还是不合适的。在 RESTful 具体实践中多得是比“ URL 中能不能出现动词”这样的问题更加重要的问题要去解决,没必要在这个问题上多纠结。
    看看 github 的 search api : https://developer.github.com/v3/search/#search-repositories
    hantsy
        22
    hantsy  
       2015-10-02 11:28:46 +08:00
    @imzshh 大部分情况是可以利用 HTTP 语义避免,少数情况下不得回避这些原则(如 /auth/signup, /auth/signin, 查询参数太多时,可能改 POST 查询,通过 Body 传递更多的参数)。 Github API , Heroku 是设计上比较的 API 典范。

    REST , Rechardson Mature Model 都是约定,不是规范。

    但 HAL 是规范。
    yangyuan
        23
    yangyuan  
       2015-10-02 11:33:26 +08:00
    RESTful 本身 url 里只有可能有两种实体。
    资源 和 服务,这样设计的目的是动词可以用 HTTP 的方法来代替。

    私以为 RESTful 是一种 API 设计的规则样式,但这个规则样式并不是最直观方便的,也不是很适合浏览器。
    很多被认为“错误”的用法,完全可以另总结为 “ ACTIONful ”,“ WEBful ” 什么的。
    imzshh
        24
    imzshh  
       2015-10-02 11:34:32 +08:00
    @hantsy 是的,所以我一直说的是风格而不是规范。
    PS :你例举的这个可以用 POST /access-tokens, DELETE /access-tokens/<token> 这样的 URL 形式。
    codeek
        25
    codeek  
       2015-10-02 11:49:22 +08:00
    RESTful 的简单理解,可以分成三个层次:
    1. 所有的 URL 指代的对应物都是一组资源 - resources;

    2. 基于 1 ,自然不适合在 URL 中使用任何动词,所以推荐直接使用 HTTP 标准中的动词(verb: GET, PUT, POST, DELETE)来表示对资源的操作;

    3. Hypermedia as the Engine of Application State(HATEOAS). 简而言之,服务器的每次响应中应该包含当前请求资源所有相关联资源的定位信息。举个例子:请求分页,如果下一页请求已经枯竭,那么本次请求的响应中应该标识下一页请求的定位 URL 为空。
    semicircle21
        26
    semicircle21  
       2015-10-02 17:36:45 +08:00
    @Lucius
    @imzshh
    @canesten
    url 可以用动词的名词形式, 比如 对这个主题的点赞操作, 我可能会设计成这样:
    https://v2ex.com/t/225164/upvoters
    点赞就发 post, 获取点赞者列表就 get, 删除就往这个 url 上发 delete.

    是不是动词没什么好纠结的, 真正实践 restful 的时候, 远有比这个麻烦的多的坑... 特别是面向移动客户端的时候, 完全按 restful 设计往往导致一个界面要好几个请求才能加在完, 体验像 shi 一样.
    msg7086
        27
    msg7086  
       2015-10-02 20:14:42 +08:00
    @Lucius 「上菜了,请动筷子吧」 = 禁止筷子以外的餐具
    资源如果只能做 CRUD 动作的话,就等于要把一大票业务流程都归并到 Update 上,反而造成接口混乱。
    比如我要有购买商品功能,要怎么设计路由?
    karloku
        28
    karloku  
       2015-10-03 04:01:47 +08:00
    其实参考了 elasticsearch 的 api 设计方式, 觉得 uri 里包含动词也不是一件天崩地裂的事情, 也就是在 crud 之外.
    比如我有一串资源是 /items, 这些 items 是支持排序的, 那么我排序的接口应该怎么设计呢.

    PUT /items
    {
    "_action": "reorder",
    "params": {...}
    }
    这样似乎就会污染 update 这个街口, 变得很复杂

    把路由放到
    PUT /items/orders
    操作实际上不存在的 orders 资源. 总觉得有种自欺欺人的感觉. 这种做法最常见的是用在搜索或者点赞上. 但是前者的确因为请求而产生了一次性的资源. 而后者也是可以勉强算是嵌套在某个资源内部的资源.

    或者是针对所有资源进行
    PUT /items/x
    去更新每一个 item 的 order. 这个好像 restful 了, 不过使用起来会变的非常麻烦...

    最后尝试下来做下来还是包含一个动词的 URI, 会让 api 的语义更清楚:

    POST /items/_reorder
    legendlee
        29
    legendlee  
    OP
       2015-10-03 11:48:28 +08:00 via Android
    @msg7086 没做过电商系统,但是按照之前做管理系统的经验,购买商品这种操作,在系统内部应该叫“创建一个订单”吧。
    SmiteChow
        30
    SmiteChow  
       2015-10-06 21:10:37 +08:00
    最标准的 restful 可以参考 swagger 设计
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1123 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 18:39 · PVG 02:39 · LAX 10:39 · JFK 13:39
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.