ChatGPT解决这个技术问题 Extra ChatGPT

REST、HTTP DELETE 和参数

关于为 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 问题,而且并非所有客户端都希望确认删除。

建议任何人?

您的 Roy 论文的 url 包含一个“)”,它会导致 404。ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm 有效。

C
Community

不,它不是 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 请求,它应该在不需要任何额外确认的情况下处理它(无论服务是否实际执行操作)。


您能解释一下违反了哪个 REST 约束吗?考虑到 URI 对客户端应该是不透明的,为什么您认为使用删除一个资源但无法删除另一个资源的 HTTP DELETE 无法满足客户端的期望。我不确定 409 是返回的最佳状态代码,但除了有点奇怪的实现之外,我找不到任何被破坏的 REST 约束。
@Darrel:(恕我直言)它违反了 DELETE 方法的统一接口,没有按照 HTTP 标准执行。考虑一个假定标准 REST 服务的 REST 客户端 - 该服务如何让客户端知道它需要添加 force_delete=true?根据 HTTP RFC,DELETE 方法可能会在源服务器(客户端)上被覆盖,这意味着这不是在目标服务器(服务)上完成的。所以我的理解是,一旦服务收到 DELETE 请求,它应该在不需要任何确认的情况下处理它(无论服务是否实际执行操作)。
@Chris,您的第二点:是的,这也是我的理解,即状态表明存在真正的冲突,而不需要确认。我刚刚注意到您在问题中所做的更新,我同意 - 当我自己研究它时,我得出了相同的结论(这违反了统一界面,并且应该在客户端/UI上进行确认边)。我还在这里遇到了一个非常有趣的线程,它可能会有所帮助:mail-archive.com/pylons-discuss@googlegroups.com/msg13578.html
@MicE 在很大程度上我同意你的观点,这不是处理这种情况的理想方式。我只是对“它不是 RESTful”标签有点挑剔。有一段时间,这句话被扔在了所有地方。但是,可以为媒体类型定义规则,如果您尝试删除资源并收到错误(我会说 403 禁止会比 409 更好),那么客户端应该尝试删除相关资源通过添加“force_delete=true”。在某种程度上,它有点像授权。执行 GET,获取 401,添加 auth 标头并再次 GET。
@Darrel:这是一个很好的观点,谢谢。而且我看到人们自己贴上非 RESTful 标签。可能是现在服务和 Web 应用程序之间的障碍变得非常模糊,所以一组人可以从纯服务的角度看到这一点,而另一些人则从混合的应用程序/服务的角度来看。这就是我相信关于如何进行确认的真正问题所在。 @Chris:更新了-谢谢先生,一个非常有趣的话题和讨论!
A
Alex Rockwell

我认为这是不平静的。我认为 restful 服务不应该处理强制用户确认删除的要求。我会在 UI 中处理这个问题。

如果这是程序的 API,那么指定 force_delete=true 是否有意义?如果有人正在编写脚本来删除此资源,您是否要强制他们指定 force_delete=true 以实际删除该资源?


您回复的第一段是您的意见,我尊重这一点,但您没有指出文献中禁止使用这样的 URI 的内容 - 它仍然标识资源并且正在使用最合适的 HTTP 动词。回答您的问题;是的,它仍然有意义(在我看来)。我希望脚本(可能基于 CURL)尊重 409 响应并向用户建议如何重新发送请求 - 所有这些都基于我的响应正文
关于将 Web API 与程序的 API 进行比较的要点。这通常是确定 API 是否为 RESTful 的好方法。
S
Shay Rojansky

这是一个老问题,但这里有一些评论......

在 SQL 中,DELETE 命令接受一个参数“CASCADE”,它允许您指定依赖对象也应该被删除。这是一个有意义的 DELETE 参数示例,但 'man rm' 可以提供其他参数。这些情况如何在没有参数的情况下在 REST/HTTP 中实现? @Jan,URL 的路径部分标识资源似乎是一个公认的约定,而查询字符串没有(至少不一定)。例子比比皆是:获取相同的资源但格式不同,获取资源的特定字段等。如果我们将查询字符串视为资源标识符的一部分,则不可能有“同一资源的不同视图”的概念无需转向非 RESTful 机制,例如 HTTP 内容协商(由于许多原因,这可能是不可取的)。


感谢您将其添加到对话中,即使它持续了数年以来并没有太多的对话。
J
Jason

除了亚历克斯的回答:

请注意,http://server/resource/id?force_delete=true 标识的资源与 http://server/resource/id 不同。例如,删除 /customers/?status=old 还是 /customers/ 有很大的不同。


我不同意,我可以自由地提供多个 URI 来标识相同的资源。
是的-每个人都可以随意弄乱:-)
规范 URI 的指示可以对此有所帮助:googlewebmastercentral.blogspot.com/2009/02/…
@Chris应该只有一个返回资源表示的URI。其他 URI 可以引用相同的概念,但执行 GET 应该返回 303 See Other。为了反驳对此的明显反对意见,/foo.xml 和 /foo.json 是两个不同的资源。
@Darrell - 同意,但格式在这里不是问题。此外,.format 是 Rails 和其他框架中的约定,不是 REST 的一部分——您应该使用 HTTP 中的内容协商与 MIME 或微格式来完全实现这一点。