关于为 HTTP DELETE 请求提供参数有什么非 RESTful 的吗?
我的场景是我正在建模“你确定要删除它吗?”设想。在某些情况下,资源的状态表明请求的删除可能无效。您可以自己想象一些需要确认删除的场景
我们采用的解决方案是给删除请求传递一个参数,表示可以继续删除("?force_delete=true")
例如
DELETE http://server/resource/id?force_delete=true
我相信它仍然很平静,因为:
(a) DELETE 的语义没有改变 - 用户仍然可以发送正常的 DELETE 请求,但这可能会失败并返回 409,响应正文将解释原因。我说可能会失败,因为(出于不值得解释的原因)在某些情况下没有理由提示用户。
(b) Roy 的论文中没有任何内容表明它违背了 REST 的精神——为什么会有,因为 HTTP 只是 REST 的一种实现,那么为什么传递 HTTP 参数很重要
有人可以指出一个明确的声明来说明这不是 RESTful 的原因吗?
在一个相关问题上,如果用户没有指定 force_delete,那么我将返回 409 Conflict
- 这是最合适的响应代码吗?
跟进
经过进一步研究,我认为在 DELETE 中添加参数可能会违反几个原则。
首先是实现可能违反了“统一接口”(参见 Roy's dissertation 的第 5.1.5 节
通过添加“force_delete”,我们在已经定义好的 DELETE 方法上添加了一个额外的约束。这个约束只对我们有意义。
您也可以争辩说它违反了“5.1.2 客户端-服务器”,因为确认对话实际上是一个 UI 问题,而且并非所有客户端都希望确认删除。
建议任何人?
不,它不是 RESTful。您应该将动词 (force_delete
) 放入 URI 的唯一原因是,如果您需要在 PUT/DELETE 方法不可用的环境中重载 GET/POST 方法。从您使用 DELETE 方法来看,情况并非如此。
HTTP 错误代码 409/Conflict
应该用于存在冲突而阻止 RESTful 服务执行操作的情况,但用户仍有可能自己解决冲突。删除前确认(没有会阻止删除的真正冲突)本身并不是冲突,因为没有任何东西可以阻止 API 执行请求的操作。
正如亚历克斯所说(我不知道谁对他投了反对票,他是正确的),这应该在 UI 中处理,因为这样的 RESTful 服务只是处理请求,因此应该是无状态的(即它不能通过持有来依赖确认有关请求的任何服务器端信息)。
如何在 UI 中执行此操作的两个示例是:
pre-HTML5:* 向用户显示一个 JS 确认对话框,并且只有在用户确认后才发送请求
HTML5:* 使用带有操作 DELETE 的表单,其中表单将仅包含“确认”和“取消”按钮(“确认”将是提交按钮)
(*) 请注意,5 之前的 HTML 版本本身不支持 PUT 和 DELETE HTTP 方法,但是大多数现代浏览器可以通过 AJAX 调用来执行这两种方法。有关跨浏览器支持的详细信息,请参阅 this thread。
更新(基于额外的调查和讨论):
服务需要存在 force_delete=true
标志的场景违反了 Roy Fielding 论文中定义的 uniform interface。此外,根据 HTTP RFC,DELETE 方法可能会在源服务器(客户端)上被覆盖,这意味着这不是在目标服务器(服务)上完成的。
因此,一旦服务接收到 DELETE 请求,它应该在不需要任何额外确认的情况下处理它(无论服务是否实际执行操作)。
我认为这是不平静的。我认为 restful 服务不应该处理强制用户确认删除的要求。我会在 UI 中处理这个问题。
如果这是程序的 API,那么指定 force_delete=true 是否有意义?如果有人正在编写脚本来删除此资源,您是否要强制他们指定 force_delete=true 以实际删除该资源?
这是一个老问题,但这里有一些评论......
在 SQL 中,DELETE 命令接受一个参数“CASCADE”,它允许您指定依赖对象也应该被删除。这是一个有意义的 DELETE 参数示例,但 'man rm' 可以提供其他参数。这些情况如何在没有参数的情况下在 REST/HTTP 中实现? @Jan,URL 的路径部分标识资源似乎是一个公认的约定,而查询字符串没有(至少不一定)。例子比比皆是:获取相同的资源但格式不同,获取资源的特定字段等。如果我们将查询字符串视为资源标识符的一部分,则不可能有“同一资源的不同视图”的概念无需转向非 RESTful 机制,例如 HTTP 内容协商(由于许多原因,这可能是不可取的)。
除了亚历克斯的回答:
请注意,http://server/resource/id?force_delete=true
标识的资源与 http://server/resource/id
不同。例如,删除 /customers/?status=old
还是 /customers/
有很大的不同。
force_delete=true
?根据 HTTP RFC,DELETE 方法可能会在源服务器(客户端)上被覆盖,这意味着这不是在目标服务器(服务)上完成的。所以我的理解是,一旦服务收到 DELETE 请求,它应该在不需要任何确认的情况下处理它(无论服务是否实际执行操作)。