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

2017-02-15 12:59:26 +08:00
 noli

不少程序员都是这么认为的,基于 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 写的客户端来说,恐怕就忍不住要问候服务端程序员一家了。

更重要的是……

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

全文完,欢迎拍砖。

40927 次点击
所在节点    程序员
207 条回复
6IbA2bj5ip3tK49j
2017-02-15 13:08:28 +08:00
问题在于,加上 delete 和 put 也是不够的。
那些状态码也是不够的。
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
2017-02-15 13:11:42 +08:00
其实,有 POST 就够了, GET 都是多余的
m939594960
2017-02-15 13:11:47 +08:00
主要是状态码完全不够用,大部分都需要 先获取一下 header 判断是否正确,然后解析 json 判断 code 代码。、
wingoo
2017-02-15 13:13:57 +08:00
至于前端调用解析结果, 这个不管是否使用 restful 都需要前端去判断
而统一的结构只会有好处, 不会有坏处
更何况, 错误还可以统一处理啊

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

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

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

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

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

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

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

如果不是事务式的,那么分别执行 POST 和 DELETE

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/340607

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX