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 写的客户端来说,恐怕就忍不住要问候服务端程序员一家了。

更重要的是……

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

全文完,欢迎拍砖。

40332 次点击
所在节点    程序员
207 条回复
fucker
2017-02-15 14:59:55 +08:00
POST .../ResourceXYZ?action=delete/add/update
kulove
2017-02-15 15:01:58 +08:00
风格而已,没必要完全遵守
noli
2017-02-15 15:08:41 +08:00
@wizardoz 说得太好了。要的就是优雅。

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

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

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

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

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

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

```
{
[
{"method": "POST", "resource": "/someResources", "args": {...} },
{"method": "DELETE", "resource": "/someResource/1234"},
]
}
```
你这个是 restful ?
hronro
2017-02-15 15:55:56 +08:00
所以讲道理,最终还是 GraphQL 最好😂
menc
2017-02-15 16:00:05 +08:00
逻辑不对啊, 404 , 403 状态码是针对 URL 的,不是针对动作的,它只能标识该 URL 的相关信息,不能用状态吗来作为后端逻辑执行结果的证明。
lxrmido
2017-02-15 16:00:24 +08:00
你说得很有道理,假如我是三十年前的程序员我一定支持你。
noli
2017-02-15 16:00:43 +08:00
@PhilC 里面的 JSON 是手打的,确实是格式不对。
但 POST 一个 JSON 有什么问题么? 为什么觉得不是 RESTful ?
noli
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
2017-02-15 16:10:12 +08:00
```
{
[
{"method": "TEST", "resource": "/someResource/1234"},
]
}
```
我 POST 一条这样的 JSON ,你是不是也要返回 HTTP 405 Method Not Allowed
rogerchen
2017-02-15 16:15:48 +08:00
以前是绝对路径 / 后边是 CGI ,?后边是传给 CGI 的参数。
restful 把参数写在路径里,搞万物都是 URI ,方法作为动作参数。

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

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

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

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

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

© 2021 V2EX