RESTful 有用吗? HTTP 有 GET POST 就足够了? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
noli
V2EX    程序员

RESTful 有用吗? HTTP 有 GET POST 就足够了?

  •  
  •   noli 2017-02-15 12:59:26 +08:00 42226 次点击
    这是一个创建于 3160 天前的主题,其中的信息可能已经有所发展或是发生改变。

    不少程序员都是这么认为的,基于 HTTP API 的服务,只要用 GET 请求和 POST 请求就足够了。 像 RESTful 这样的 大量使用 PUT , DELETE 请求是不必要的。

    真的吗,我来举一个例子。

    假设有一类资源 ResourceXYZ ,对其有增删查改的操作。 如果只使用 GET POST 之类的设计方式,那么很可能会设计以下的请求接口:

    POST .../addResourceXYZ POST .../delResourceXYZ GET .../getResourceXYZ?resourceId=resourceId POST .../updateResourceXYZ 

    如果按照 RESTful 的 设计方式,很可能会设计以下的请求接口

    POST .../ResourceXYZs DELETE .../ResourceXYZ/{resourceId} GET .../ResourceXYZ/{resourceId} PUT .../ResourceXYZ/{resourceId} 

    现在假设,客户端要获取该资源,其 ID 为 resourceId 。 如果成功,那么一切都好说。 如果失败, Restful 的处理方式是,通过 HTTP status 返回错误码来表示原因,例如 404 表示该资源不存在。

    那么只用 GET POST 两种方法的方式呢? 响应请求

    GET .../getResourceXYZ?resourceId=resourceId 

    的时候能不能也用 404 呢?

    按照 404 的语义,响应 404 是不对的: 因为客户端请求的 URL 实际上是正确的,只是对应的参数没有找到对应的结果 很多时候,就只能靠响应 200 然后返回空数据或者空对象来处理了。 例如 Content-type 为 application/json 时,可以返回 {} 或者

    { "error": "not found", "code": 404 } 

    这样就会要求客户端,必须处理 HTTP 回复的具体内容,而不能只处理头部。 那么客户端要怎么处理这个 json 呢 要先解析 json ,然后尝试分别这是一个资源的内容,还是一个错误提示。

    对于强类型语言例如 C/C++ OC Swift 写的客户端来说,恐怕就忍不住要问候服务端程序员一家了。

    更重要的是……

    没有库会支持这种拍脑袋式的设计。

    全文完,欢迎拍砖。

    207 条回复    2018-09-01 23:44:06 +08:00
    1  2  3  
    6IbA2bj5ip3tK49j
        1
    6IbA2bj5ip3tK49j  
       2017-02-15 13:08:28 +08:00   1
    问题在于,加上 delete 和 put 也是不够的。
    那些状态码也是不够的。
    wingoo
        2
    wingoo  
       2017-02-15 13:08:55 +08:00
    POST .../addResourceXYZ
    POST .../delResourceXYZ
    GET .../getResourceXYZ?resourceId=resourceId
    POST .../updateResourceXYZ

    ==============
    本身 api 端是按照模块划分的
    所以
    GET .../getResourceXYZ?resourceId=resourceId
    可以划分为
    GET .../getResource1
    GET .../getResource2

    restful 只不过帮你把这些定义自动划分好了而已
    另外返回值, 默认为 200
    正确,错误 会在返回代码里统一定义
    Reign
        3
    Reign  
       2017-02-15 13:11:42 +08:00   2
    其实,有 POST 就够了, GET 都是多余的
    m939594960
        4
    m939594960  
       2017-02-15 13:11:47 +08:00
    主要是状态码完全不够用,大部分都需要 先获取一下 header 判断是否正确,然后解析 json 判断 code 代码。、
    wingoo
        5
    wingoo  
       2017-02-15 13:13:57 +08:00
    至于前端调用解析结果, 这个不管是否使用 restful 都需要前端去判断
    而统一的结构只会有好处, 不会有坏处
    更何况, 错误还可以统一处理啊

    如果这种设计叫拍脑袋设计, 那你所接触的系统基本都是拍脑袋了
    奉劝下 lz 不要迷恋权威
    restful 只是 restful 而已
    cloudyplain
        6
    cloudyplain  
       2017-02-15 13:15:03 +08:00   1
    404 的例子理解不了,个人认为 restful 去掉了 url 中的动词",简化了 url 命名。
    miyuki
        7
    miyuki  
       2017-02-15 13:17:05 +08:00
    /t/336226 相关主题……
    laxenade
        8
    laxenade  
       2017-02-15 13:20:58 +08:00
    反正都不遵守 restful 了 为什么还要遵守 404 的语义。
    Matrixbirds
        9
    Matrixbirds  
       2017-02-15 13:29:38 +08:00
    按照 spec 的 rule ,认为 get 的请求是不会对服务端状态造成改变的。 post 则会改变
    noli
        10
    noli  
    OP
       2017-02-15 13:29:54 +08:00
    @xgfan 对于资源增删查改不够的话,请问要加上什么操作?能不能举个例子?

    @wingoo 你说的 GET .../getResource1 是只把 resourceId 作为后缀填到 URL 里面去吗?那这跟 RESTful 有什么区别?
    RESTful 不能统一处理吗?能否统一处理是后端架构的问题,跟 RESTful 无关。

    @laxenade RESTful 是 HTTP 之上的概念, 404 是 HTTP 的概念,不同层。如果 HTTP 语义都不遵守,确实没啥好说的。
    noli
        11
    noli  
    OP
       2017-02-15 13:34:42 +8:00
    @wingoo

    想向你补充一句:
    按照 RESTful 的设计来做不叫迷恋权威。
    而是不必自己另外发明一套轮子。
    undeflife
        12
    undeflife  
       2017-02-15 13:35:19 +08:00
    Sequencer
        13
    Sequencer  
       2017-02-15 13:35:20 +08:00 via iPhone
    在 header 里面鉴权…
    post 发 json 指令有啥不好的……
    clino
        14
    clino  
       2017-02-15 13:39:45 +08:00
    我也只用 get/post ,其他都没用
    noli
        15
    noli  
    OP
       2017-02-15 13:42:04 +08:00
    @cloudyplain
    URL 名称叫做 Universal Resource Location ,本来只是用来表明资源的位置。
    而加上动作前缀,也不是不可以,但这种方式偏离了表示资源位置的本意,耦合了其他语义。

    例如, getResource 返回 404 ,那么可以有两种方式理解:
    1. 不看动词,表明该资源不存在
    2. 看动词,表明 1 )不存在这种资源,或者 2 )不存在对这种资源的操作,或者 3 )资源存在但不支持这种操作
    magict4
        16
    magict4  
       2017-02-15 13:46:31 +08:00   2
    如果我有个 Email 的 Service , GET/PUT/DELETE/POST 分别对应增删查改,那『发送』,『存档』,『移到文件夹 X 』又该如何表示呢?
    gamexg
        17
    gamexg  
       2017-02-15 13:50:33 +08:00 via Android
    没意义, 404 时想要返回错误信息还是需要解析返回的内容结构。
    那直接 200 不一样吗?
    kenshinhu
        18
    kenshinhu  
       2017-02-15 13:51:29 +08:00
    我发现我一起用的是 假的 RESTful
    magict4
        19
    magict4  
       2017-02-15 13:52:41 +08:00
    我支持 @xgfan 说的。在逻辑比较复杂的业务场景里, Restful 提供的 4 个动词是远远不够的。
    noli
        20
    noli  
    OP
       2017-02-15 13:54:52 +08:00
    @magict4

    如果将 Email 视作 Resource ,或者更广泛地考虑,用 RESTful 来描述 IM 消息:
    向某人发送消息,应该是在 其消息队列中 POST 一个新资源, 用
    ```
    POST /{SomeBody}/messages/
    ```
    存档某消息,其实也就是同样的意思

    移到文件夹 X 这里面略坑,因为包括两个步骤: 1. 在新位置复制一个 2. 在旧位置删除
    看需要是否做成事务式的:
    如果是事务式的,应该是事务队列增加一个资源

    如果不是事务式的,那么分别执行 POST 和 DELETE
    noli
        21
    noli  
    OP
       2017-02-15 13:56:48 +08:00
    @gamexg

    如果不需要解析错误信息呢? RESTful 能够照顾到两种需求。
    如果直接返回 200 做不到这一点。
    magict4
        22
    magict4  
       2017-02-15 14:05:20 +08:00
    @noli 我不会这么设计我的 API 的。 Messages 这个概念,是因为 Restful 只提供了 4 个动词的一种变通。我的 Server 可能通过 Message Queue 来实现消息的传递,但这种底层的东西不应该暴露给我的客户。我需要暴露给客户的,应该是类似 send email, archive email, move email 之类的接口东西,然而这并不能通过 Restulful 来直接实现。你可参考下 AWS 的服务文档
    Felldeadbird
        23
    Felldeadbird  
       2017-02-15 14:08:59 +08:00
    我个人认为 GPPD 最重要的优点在于 统一了 URL 操作,节省了起名的困难。
    例如:现在 CURD 都是 /article/1.html 。 我都不用去想起他动作了。
    换以前,/article/1.html , /addarticle/1.html, /updatearticle/1, /removearticle/1..
    murmur
        24
    murmur  
       2017-02-15 14:11:43 +08:00
    以现在的框架 restful 更多成为一种形式或者信仰 除了 json 发出和 json 结果比较讨人喜欢 其余的没啥问题
    比如 /api/removeItem 和 /api/item 发 del 有什么区别么?前者如果命名一致文档合理同样是优秀设计
    noli
        25
    noli  
    OP
       2017-02-15 14:12:25 +08:00
    @magict4

    我说的 Messages 是类似于论坛消息之类的业务 Message , Email 概念的泛化、抽象化。
    你当然可以不用 Restful 来实现,而且我本人也不建议。
    你要我举个例子,那我就免为其难了。

    事实上,我认为,操作系统的全部 系统调用,都可以用 RESTful API 来对应表示。
    不习惯的人可能会觉得别扭,但是是可行的、科学的、经得起考验的。
    noli
        26
    noli  
    OP
       2017-02-15 14:13:28 +08:00
    @murmur

    "比如 /api/removeItem 和 /api/item 发 del 有什么区别么?"

    见 #15
    wshcdr
        27
    wshcdr  
       2017-02-15 14:14:07 +08:00
    我认为采用 restful 的话, 客户端(包括移动端)是要自己维护自己的业务接口的,服务端只是暴露 GET/PUT/DELETE/POST 分别对应增删查改

    对应发邮件的例子,也就是客户端要自己实现发送这种功能,自己在发送功能里协调对 GET/PUT/DELETE/POST 的调用。
    mcfog
        28
    mcfog  
       2017-02-15 14:17:46 +08:00   3
    1. restful 是风格不是规范
    2. 如果楼主如果真心认为“ POST /updateXYZ?id={id}”和“ PUT /XYZ/{id}”对等,那我觉得并不能说是真正理解了 restful
    3. 正如其他很多同学说的, restful 的状态码数量有限,用于表示复杂的业务问题经常不够,基本最终还是要在 body 里定义自己的错误描述体系
    4. restful ,状态, cookie , session 之间的关系我一直没找到权威说明。业界常见的 restful 风格接口大多用非 cookie 的令牌 token+服务端 session 来处理状态,此时接口连基本的在 web 端和 app 复用都得讨论了( token 让 js 自己存储和 secure httpOnly 的 cookie 的安全性差距)欢迎指教
    5. 把接口分两大块:
    a) 业务接口( app/web 等使用的),这类接口我倾向全 POST 或幂等读 GET 其他 POST ,返回结构统一 code,message,body 的风格, HTTP 状态码用来表述“通信状态”, body 内返回吗表述“业务状态”
    b) 后端接口( CGI 端再调其他 server 用的),这类接口如果业务逻辑量小,贴近“资源 CRUD ”的 restful 最贴切的领域的话,我会考虑 restful 作为备选方案
    magict4
        29
    magict4  
       2017-02-15 14:22:17 +08:00
    @noli 你看看我有没有误解你的意思。拿『移动到文件夹 X 』举例。

    如果是事务的,我猜你对应的 URL 会是
    post .../MoveEmailTransaction

    如果不是事务的,你说会用两个 HTTP request 来实现,那对应的 URL 肯定跟上面的会有所不同。

    如果我的理解是对的话,同样的一件事情,因为实现不同,对应的接口变了。在我看来,好的 API 设计应该是无论实现怎样, API 应该保持稳定。所以我会用
    post .../moveEmail?source=???&&destination=???

    > 但是是可行的、科学的、经得起考验的
    如果因为实现的不同,需要改变 API 的设计,我不太能认同是科学的。

    我的主要观点是, Restuful 提供的 4 个动词是远远不够的。在复杂的业务场景里面,如果想用这 4 个动词来表示所有操作,往往会让 API 的设计变的更加困难。
    baiyi
        30
    baiyi  
       2017-02-15 14:22:35 +08:00   1
    RESTful 说到底也只是众多 Api 规范 中的其中之一, 它是有一定的适用性的.

    在 RESTful 适用性之外的项目,就不要强行上 RESTful 了

    现在 Api 的规范都和语言之争一样火爆了......
    baiyi
        31
    baiyi  
       2017-02-15 14:24:05 +08:00
    @baiyi 口误,RESTful 是设计风格不是设计规范
    div id="r_4044536" class="cell">
    otakustay
        32
    otakustay  
       2017-02-15 14:34:31 +08:00
    restful 是架构风格,不是接口设计风格,如果你做不到 restful 架构,请不要在接口这么个东西上盲目追求 restful
    gevin
        33
    gevin  
       2017-02-15 14:37:52 +08:00   1
    又想提一下我原来写的两篇博客:

    RESTful 架构风格概述: http://blog.igevin.info/posts/restful-architecture-in-general/
    RESTful API 编写指南: http://blog.igevin.info/posts/restful-api-get-started-to-write/
    noli
        34
    noli  
    OP
       2017-02-15 14:41:37 +08:00
    @magict4

    在一个 openstack 相关的业务里面,我用 RESTful 实现过对 AD ( ActiveDirectory )相关的接口 WEB 封装。
    里面也是经常有对各种简单的、原子的 对各种 AD 条目的操作的 组合所形成的事务。
    提交事务方法只有一种:
    ```
    POST .../Transaction
    ```
    然后在请求体里面用 JSON 描述这个事务的各种操作和参数,例如:

    ```
    {
    [
    {"method": "POST", "resource": "/someResources", "args": {...} },
    {"method": "DELETE", "resource": "/someResource/1234"},
    ]
    }
    ```
    实际上就是把一连串的 RESTful API 调用转化成一个 JSON 对象来描述要执行的事务。

    所以你说“同样的一件事情,因为实现不同,对应的接口变了” 实际上不存在~ :)
    zweite
        35
    zweite  
       2017-02-15 14:47:31 +08:00
    想象当 Restful 遇到爬虫会怎么样
    msg7086
        36
    msg7086  
       2017-02-15 14:50:06 +08:00
    为了去套 RESTful 而强行把不是资源或者不适合以资源形式访问的东西也当做资源,就是个问题了。
    这有点像数据库的范式,你可以把范式堆得老高,但是实际开发中没人会真的这么干,意思意思做得干净点就行了。
    顺便提一句,很多实现里(比如浏览器), HTTP 动词是只支持 GET/POST 的, PUT/DELETE 都要用 _method=? 之类的来传递,然后在上层去抽象。
    baiyi
        37
    baiyi  
       2017-02-15 14:50:08 +08:00
    @zweite RESTful 跟爬虫关系不大, 因为他返回较为完整的 http 信息,或许对爬虫更加友好
    whx20202
        38
    whx20202  
       2017-02-15 14:51:58 +08:00
    @otakustay 我一直以为是接口设计风格。

    给你这么一说我才反应过来 肯定有很多接口看起来 restful 实际后端架构并不是
    baiyi
        39
    baiyi  
       2017-02-15 14:52:04 +08:00   1
    http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api
    这篇文章是我看来关于 Api 中 RESTful 的实践 中最好的一篇文章了

    想要更深的了解 REST,可以去找找博士的论文读
    wizardoz
        40
    wizardoz  
       2017-02-15 14:55:43 +08:00   2
    非要说够不够的,那我说一个 POST 就够了,还要 GET 干啥?
    所以我们要的不是够,我们要的是优雅。
    fucker
        41
    fucker  
       2017-02-15 14:59:55 +08:00
    POST .../ResourceXYZ?action=delete/add/update
    kulove
        42
    kulove  
       2017-02-15 15:01:58 +08:00 via iPhone
    风格而已,没必要完全遵守
    noli
        43
    noli  
    OP
       2017-02-15 15:08:41 +08:00
    @wizardoz 说得太好了。要的就是优雅。

    那些说 RESTful 是 风格而不是规范的同志们,扯这个没用。
    你看看各大平台下的各种 RESTful 相关的库,你就知道什么是风格什么是规范了。
    遵守这个风格也好,规范也好,就提供一种使用开源代码的机会。
    不遵守也不是不行,自己掌握细节,然后实际上是把 RESTful 的规范用另外一种形式实践一遍。
    neutrino
        44
    neutrino  
       2017-02-15 15:08:55 +08:00
    即使是资源的 CRUD ,也不推荐用 Restful 。 HTTP 状态应当仅由 HTTP 服务器处理,如 404 是指没有找到处理的程序,而不是程序处理了发现资源没找到。任何经处理的结果应当一律以 HTTP 200 返回,表示这是一次成功的 HTTP 请求,并在 body 中表示请求的结果。
    noli
        45
    noli  
    OP
       2017-02-15 15:14:31 +08:00
    @neutrino

    只使用 HTTP 200 , Content-type 都是 JSON
    缓存服务器要怎么判断返回的是成功处理的结果,还是出错提示?
    neutrino
        46
    neutrino  
       2017-02-15 15:34:58 +08:00
    @noli 对于动态处理的内容不应当缓存,不推荐 urlrewrite ,每一个 url 都应当是实际存在的文件,仅缓存静态文件。应当显式暴露入口文件。
    Balthild
        47
    Balthild  
       2017-02-15 15:43:28 +08:00
    @noli 说得对啊,只是要优雅罢了。如果不用 REST 比用 REST 更优雅,那为什么要用 REST 呢?
    hxtheone
        48
    hxtheone  
       2017-02-15 15:45:25 +08:00
    请求方式表示行为, URL 表示资源, 个人表示很喜欢, 在 URL 里带上动词总是感觉太嗦了点
    noli
        49
    noli  
    OP
       2017-02-15 15:49:48 +08:00
    @neutrino

    “动态处理的内容不应当缓存”? 明明基于 HTTP 动作、状态码和特定 HTTP 头就能实现的事情,硬生生因为你非要返回 200 而自废武功。

    “每一个 url 都应当是实际存在的文件” HTTP 3XX 也可以不用了是吧?

    所以你这是把规范的实现的效果,在写代码的时候实践了一遍
    还不如老老实实遵守全套的 RESTful 规范呢
    noli
        50
    noli  
    OP
       2017-02-15 15:51:12 +08:00
    @Balthild

    请举一个 HTTP 上更优雅的设计风格。
    PhilC
        51
    PhilC  
       2017-02-15 15:55:56 +08:00
    ```
    POST .../Transaction
    ```
    然后在请求体里面用 JSON 描述这个事务的各种操作和参数,例如:

    ```
    {
    [
    {"method": "POST", "resource": "/someResources", "args": {...} },
    {"method": "DELETE", "resource": "/someResource/1234"},
    ]
    }
    ```
    你这个是 restful ?
    hronro
        52
    hronro  
      &nbp;2017-02-15 15:55:56 +08:00
    所以讲道理,最终还是 GraphQL 最好
    menc
        53
    menc  
       2017-02-15 16:00:05 +08:00
    逻辑不对啊, 404 , 403 状态码是针对 URL 的,不是针对动作的,它只能标识该 URL 的相关信息,不能用状态吗来作为后端逻辑执行结果的证明。
    lxrmido
        54
    lxrmido  
       2017-02-15 16:00:24 +08:00
    你说得很有道理,假如我是三十年前的程序员我一定支持你。
    noli
        55
    noli  
    OP
       2017-02-15 16:00:43 +08:00
    @PhilC 里面的 JSON 是手打的,确实是格式不对。
    但 POST 一个 JSON 有什么问题么? 为什么觉得不是 RESTful ?
    noli
        56
    noli  
    OP
       2017-02-15 16:07:16 +08:00
    @menc

    https://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6

    The Status-Code element is a 3-digit integer result code of the attempt to understand and satisfy the request

    所以并不是只针对 URL 的。
    事实上 HTTP 405 Method Not Allowed 就是针对你的说法的反例。
    PhilC
        57
    PhilC  
       2017-02-15 16:10:12 +08:00
    ```
    {
    [
    {"method": "TEST", "resource": "/someResource/1234"},
    ]
    }
    ```
    我 POST 一条这样的 JSON ,你是不是也要返回 HTTP 405 Method Not Allowed
    rogerchen
        58
    rogerchen  
       2017-02-15 16:15:48 +08:00
    以前是绝对路径 / 后边是 CGI ,?后边是传给 CGI 的参数。
    restful 把参数写在路径里,搞万物都是 URI ,方法作为动作参数。

    我个人觉得就是两种不一样的范式, restful 主要搞 CRUD 这种比较简单的东西, CGI 更适合搞参数比较复杂的系统。
    rogerchen
        59
    rogerchen  
       2017-02-15 16:18:08 +08:00
    @noli URL 确实是 locate 资源的, CGI 不过是 locate 到了一个脚本。
    baiyi
        60
    baiyi  
       2017-02-15 16:23:45 +08:00
    @hronro GraphQL 有什么可学习的资料吗?
    noli
        61
    noli  
    OP
       2017-02-15 16:24:59 +08:00
    @PhilC

    在我那个实现里面, POST Transaction 的时候大多数情况下返回 200 以及事务 ID
    然后根据 事务 ID 查询 事务状态的时候,会给出事务的状态、结果什么的。

    当然,这个设计是有不足之处的,例如 事务里面的前后两条如果有输出间的依赖关系的话,目前是实现不了的。
    但是,你举的这个例子也太 TM 弱智了吧……?
    hronro
        62
    hronro  
       2017-02-15 16:38:59 +08:00   1
    undeflife
        63
    undeflife  
       2017-02-15 17:01:12 +08:00
    @magict4 后几个都可以用 patch 因为是修改状态
    Sight4
        64
    Sight4  
       2017-02-15 17:02:26 +08:00   1
    这个 topic 在 V2EX 已经引战 N 次...

    1. 在经历多个前后端分离的坑之后,从结果上看,完全符合的 restful 规范风格的 api 是很难实现(应该说是实现起来反而很别扭)

    2. 但是 restful 风格的 URL 、幂等性、授权对于设计基于 web 的 api 是很有指导意义的,所以最终在项目实施的时候,很多时候都会按照资源来划分 url ,但是不再使用 http 返回码以及 method 来表达资源的结果和用途,毕竟, API 文档还是要写的嘛

    3. 其实,统一的 http post 在某种意义上很方便前端对 api 的封装
    chairuosen
        65
    chairuosen  
       2017-02-15 17:06:30 +08:00
    又来引战了
    noli
        66
    noli  
    OP
       2017-02-15 17:10:03 +08:00
    @msg7086

    漏了回复你。
    对于某些浏览器不支持 GET POST 之外的动作,可以用 http method override
    baiyi
        67
    baiyi  
       2017-02-15 17:37:36 +08:00
    @Sight4
    @chairuosen

    虽说我也认为楼主有点引战的意思.
    但是,这类的"战争"我觉得还是有一定意义的.
    能引得起来,就说明还是存在着许多人不认同的地方,有了更多的讨论,融会贯通嘛,对自身的理解也很有帮助
    noli
        68
    noli  
    OP
       2017-02-15 17:39:44 +08:00
    @Sight4

    1. 因为很多人根本没有操刀设计 API 的水平。别说 RESTful 了,我厂也算知名互联网企业,某 C++ SDK 出品一样是个渣渣。 RESTful 要考虑的更多难度更高,但说 RESTful 会导致实现别扭…… 呵呵

    2. HTTP 返回码和 回复里面的返回码,通常其含义不应该是冲突的,诸如 HTTP 200 但是 "code": 404 这种只能说某些人自以为很了解 HTTP 协议及其客户端。


    3. 不用 HTTP method ,那么基本上就是把动作写在 URL 里面,这种设计我觉得见仁见智,有些时候是很省事,但通常深挖一下就会发现是解耦不够。
    更重要的是,这基本上等于放弃了各种 RESTful client SDK 带来的好处。
    那还不如直接点干脆不用 HTTP

    所以我觉得你说了很多没有经过深入思考的经验,但基本上是废话。
    guokeke
        69
    guokeke  
       2017-02-15 17:41:36 +08:00 via Android
    restful 已死。 graphql 当立。
    Sight4
        70
    Sight4  
       2017-02-15 18:10:58 +08:00 via iPhone   1
    @baiyi 唉,主要是每次引战,非得要说那个是适合,那个不适合,抛开场景来啥扯一般很难有结论, restful 优雅,但 db 设计的三范式何尝不是?度是很重要
    cnt2ex
        71
    cnt2ex  
       2017-02-15 18:20:12 +08:00
    URL 不是 Uniform Resource Locator 吗?
    Actrace
        72
    Actrace  
       2017-02-15 18:30:25 +08:00
    猩球大战开始了。
    Lucups
        73
    Lucups  
       2017-02-15 18:42:56 +08:00
    同样的话题这已经是我看到过的第 4 篇 topic 了。

    看到现在的评论,我的感觉是大多数人倾向于:
    restful 不错,有借鉴意义,但我只会有限使用或者在不会去用。
    lightening
        74
    lightening  
       2017-02-15 18:52:29 +08:00
    @magict4 仔细想的话,其实都是对资源的操作。

    发送是 CREATE 了一个 delivery ,移动和归档是 UPDATE 了状态(或位置,取决于你的实现)。我倒不是觉得做 API 应该永远按照 RESTful 设计,但确实仔细想想的话,确实至今我没有遇到任何不能 fit 进 REST 的操作。

    推荐 DHH 的关于 RESTful 的演讲:
    jsq2627
        75
    jsq2627  
       2017-02-15 20:13:22 +08:00
    restful 是信仰,不是一言两语能说清楚的。
    https://github.com/Microsoft/api-guidelines/blob/master/Guidelines.md
    pathbox
        76
    pathbox  
       2017-02-15 21:31:41 +08:00
    怎么会没有人用呢
    zhengkai
        77
    zhengkai  
       2017-02-15 21:36:35 +08:00
    忘了 RESTful 吧,去了解 GraphQL
    zonyitoo
        78
    zonyitoo  
       2017-02-15 23:25:55 +08:00
    其实 GET 也是多余的,只需要 POST
    Balthild
        79
    Balthild  
       2017-02-16 01:06:52 +08:00
    @noli 别转移话题,我说的不是什么东西比 REST 更优雅,我说的是在不用 REST 更优雅的前提下就不要用 REST 。
    请求的东西不是资源时, REST 一点都不优雅。
    noli
        80
    noli  
    OP
       2017-02-16 01:50:21 +08:00
    @Balthild

    你要说优雅,那你优雅的标准是什么?举个例子都没有,我很难跟你说话哦。

    又说请求的东西不是资源,什么东西不能视作资源来被管理呢?除了无限的东西之外。

    你没有办法用合适的方式把要管理的东西视作资源
    我见到的很多程序员都这样,例如楼上某层不知道事务怎么用资源视觉来处理
    就说 RESTful 不优雅,这是拒绝承认自己有问题。
    magict4
        81
    magict4  
       2017-02-16 05:22:20 +08:00
    @lightening 我暂时还没开看你贴的视频,有时间的话会看。

    如果我没有理解错,你跟楼主的意思应该都是

    sendEmail 对应的是 createDelivery
    moveEmail 对应的是 createTransaction

    之所以会有这样的对应,是因为 Restuful 只提供了 4 个动词。有了这样的限制,我们不得不对资源名字进行变换,把 email 变成 delivery 和 transaction 。

    我同意你说的,我们总是可以想办法把 API fit 进 Rest 这个框架 /风格。但是我不能认同我们应该这样做。
    TigerS
        82
    TigerS  
       2017-02-16 06:55:05 +08:00
    小网站感觉完全够用,但是如果稍微大点就不太方便。

    例如 DigitalOcean API ,我们自己写一个小的管理的时候基本上是
    ```
    api_url: 'https://api.digitalocean.com/v2/'
    def action(action, droplet_id):
    blah_blah(api_url + 'droplet_id' + action)
    ```
    只是举例,随便写了点

    很多东西都可以调用,而且简单易懂,而且很多可以重复利用

    但是如果全是 post 的话,就需要不断确认是 post 到了哪里,虽说也可以,但是有时候并不好用。
    baconrad
        83
    baconrad  
       2017-02-16 10:46:57 +08:00
    以前端看,今天我使用

    `GET .../ResourceXYZ/{resourceId}`

    果 server 回 HTTP status 404

    以下哪原因才是正的?

    1. client 端路境出。
    2. server 端路境出。
    3. url 入。
    4. 我要求的源不存在。
    ShiningRay
        84
    ShiningRay  
       2017-02-16 10:47:26 +08:00
    你说的是以 RPC 的风格来设计 API
    另外楼主肯定用了很麻烦的对 restful 不友好的框架
    mqtt
        85
    mqtt  
       2017-02-16 11:46:07 +08:00
    POST .../addResourceXYZ
    POST .../delResourceXYZ
    GET .../getResourceXYZ?resourceId=resourceId
    POST .../updateResourceXYZ

    这样的命名我是无法接受的,又长又丑。
    资源不存在, 本来就应该提示 404 啊, 表明用户访问的资源未找到,这样客户端就可以通过 response code 知道自己请求的资源不存在。
    mqtt
        86
    mqtt  
       2017-02-16 11:46:46 +08:00
    response status
    baiyi
        88
    baiyi  
       2017-02-16 12:33:02 +08:00
    @changwei github 大吗
    baiyi
        89
    baiyi  
       2017-02-16 12:34:12 +08:00
    @changwei github 不光有 RESTful 的, 还有 GraphQL 的
    国内的公司没有, 只能说明他们不去接触新东西,或业务不合适,代表不了其他的什么
    jybox
        90
    jybox  
       2017-02-16 12:43:17 +08:00
    其实我的想法和楼主差不多(两年多以前我也在 V2EX 发过类似的帖子),即我是觉得 RESTful 并不能覆盖到所有的情况,硬要把不适合的业务对应到「资源」是个费力不讨好的事情。但确实如果能够顺着 RESTful 的思路的话,会有一些比较方便的工具可用,所以也没有必要非要「不遵守」 RESTful 。所以我觉得在做 API 设计的时候,最重要的是项目本身能够统一和自恰,适合 RESTful 的部分就用,不适合的情况也没必要硬往上靠。

    RESTful 和 HTTP 本身的关系并没有那么密切,关于如何设计基于 HTTP 的 API 实际上不止 RESTful 一个方案。
    loading
        91
    loading  
       2017-02-16 12:44:07 +08:00 via Android
    只是参考,用 get,put,post,dekete 对于我来说就是可以少写几个路由。
    noli
        92
    noli  
    OP
       2017-02-16 13:53:22 +08:00 via iPhone
    @baconrad

    1 和 2 是不可能的因为服务器已经返回 404 了所以肯定网络没有问题

    3 和 4 都有可能
    noli
        93
    noli  
    OP
       2017-02-16 13:56:55 +08:00 via iPhone
    @ShiningRay

    猜错了,第一版后端是我写的, restful 很爽。现在我主攻客户端,后端业务升级给了另外一个人,所以我才会集中吐槽不用 restful 会给客户端带来多大的麻烦?
    wizardforcel
        94
    wizardforcel  
       2017-02-16 14:08:16 +08:00
    动态路由不等于 REST ,非 REST 也可以用动态路由 GET /ResourceXYZ/{resourceId}。

    别什么都往 REST 上套。
    TangMonk
        95
    TangMonk  
       2017-02-16 14:11:34 +08:00
    @Reign GET 可以 cache 。。
    wizardforcel
        96
    wizardforcel  
       2017-02-16 14:16:07 +08:00
    以及。。很多 http 客户端库不支持除了 get 和 post 之外的方法,遇到这种情况我真是。。。

    另外不用 REST 照样也可以设计出来优雅的路由

    增: POST /ResourceXYZ/create
    删: GET /ResourceXYZ/{resourceId}/delete
    改: POST /ResourceXYZ/update
    查: GET /ResourceXYZ/{resourceId}
    noli
        97
    noli  
    OP
       2017-02-16 14:29:18 +08:00 via iPhone
    @magict4

    我觉得设计 restful api 的时候很重要的一点是,要弄清楚业务理念哪些概念是原子性的,哪些操作是可以通过多个对原子性概念的操作组合出来的。

    如果你觉得让客户端来做这些原子性动作组合,是要求太高,那么你可以加一层 api 来接收客户端的意图,然后在这层 api 之下实现业务,

    这样通常能解决很多所谓 fit 进 restful 的问题
    wizardforcel
        98
    wizardforcel  
       2017-02-16 14:30:09 +08:00
    @noli

    > 又说请求的东西不是资源,什么东西不能视作资源来被管理呢?除了无限的东西之外。

    如果不用 REST ,某些 API 我就可以设计成

    /login
    /reg
    /tranfer

    用了 REST 就没有这些简明扼要的设计,这是不是增加复杂度呢??
    wizardforcel
        99
    wizardforcel  
       2017-02-16 14:33:27 +08:00
    @noli

    > 如果你觉得让客户端来做这些原子性动作组合,是要求太高,那么你可以加一层 api 来接收客户端的意图,然后在这层 api 之下实现业务,

    客户端做原子性动作组合存在安全隐患。

    服务端里增加一层 API 嘛。。为什么我要在 HTTP API 里面调用 HTTP API ,而不是直接调用 DAO 或者 ORM 呢??没你这么抽象的。 HTTP API 就不是给服务端自己调用的,这样粒度比 DAO 大多了。
    noli
        100
    noli  
    OP
       2017-02-16 14:44:59 +08:00
    @wizardforcel

    /login /reg /transfer
    你能用这种方式设计这些 api ,恰好说明了你的业务不需要把这些行为视作资源。
    如果你需要满足这些需求的时候,你就自然要用 restful 了

    1. 查询某用户在某时段内的 login 记录
    2. 针对某些注册申请进行人工审核,或者拒绝或者 forward
    3. transfer 是异步的,需要实时关注 transfer 是否完成

    你没有这些需求,你当然不需要把这些视作资源。

    关于“为什么要在 HTTP API 里面调用 HTTP API ”
    没有为什么,我不关心实现,因为这只是为了适应低能的客户端,怎么实现是业务需要问题。
    至于为什么 HTTP API 调用 HTTP API ,那是因为 do not repeat your self. 当这些被调用的 更底层 API 实现有变动的时候,你不需要改高层 API 的实现,虽然这也不一定是必须的。
    你连这个道理都不懂,我感觉我们的层次有差距啊。
    1  2  3  
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2435 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 37ms UTC 01:11 PVG 09:11 LAX 18:11 JFK 21:11
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86