RESTful的“ PUT”操作是否应该返回某些内容


Answers:


614

HTTP规范(RFC 2616)具有许多适用的建议。这是我的解释:

  • 200 OK成功更新现有资源的PUT的HTTP状态代码。无需响应主体。(根据第9.6节204 No Content甚至更合适。)
  • 201 Created成功地对新资源进行PUT的HTTP状态代码,在Location标头字段中返回的新资源的最具体URI,以及在响应主体中回显的资源的任何其他相关URI和元数据。(RFC 2616第10.2.2节
  • HTTP状态代码409 Conflict用于PUT是不成功的,因为一3 三方变形例中,与所尝试的更新,并在响应体中的当前资源之间的差异的列表。(RFC 2616第10.4.10节
  • 400 Bad RequestPUT失败的HTTP状态代码,响应正文中包含自然语言文本(例如英语),用于解释PUT失败的原因。(RFC 2616第10.4节

25
@stian有趣!对于Mozilla而言,这似乎很冒昧,因为我无法在RFC 2616中找到任何东西(特别是10.2成功的2xx10.2.1 200 OK部分),专门排除了200对PUT,DELETE或任何其他方法的使用。我错过了什么?例如Mozilla成为W3和IETF的老板?;)也许他们只是从未听说过Postel的稳健性原则。
系统暂停

52
@stian:该句子于2013年2月3日被删除。可能是因为有人在这里阅读了该句子。;)developer.mozilla.org/en-US/docs/HTTP/...
基督教Strempfer

6
PUT方法的语义是忽略资源处于任何当前状态,因此,对于因第3方修改而失败的PUT返回409冲突仅在请求是有条件的情况下才有意义。
Pedro Werneck 2014年

8
@systemPAUSE不错的答案。一小点:如果您不打算让响应正文返回成功的操作,我建议您仅使用204。如果某些客户端(例如jQuery Ajax)期望长度不为零的响应,但是却没有得到响应,它们将会阻塞。您可以在此问题中看到一个示例。
nick_w 2014年

3
自从回答了这个问题以来,RFC2616可能已经更新。9.6中没有提到No response body needed200。实际上,关于PUT根本没有提及响应主体。它只说If an existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to indicate successful completion of the request.
詹姆斯

164

与这里的大多数答案相反,我实际上认为PUT应该返回更新的资源(当然,除了HTTP代码之外)。

之所以要返回该资源作为对PUT操作的响应,是因为当您向服务器发送资源表示时,服务器还可以对该资源进行一些处理,因此客户端想知道如何处理该资源。请求成功完成后的外观。(否则它将不得不发出另一个GET请求)。


3
“服务器也可以对该资源进行一些处理”:这是我的新手。那真的很RESTful吗?
拉德瓦尔德

22
@Raedwald肯定是的。REST不需要在PUT上更新整个资源,尽管通常建议这样做。有些字段可能没有意义,例如,创建日期或上次修改日期可能不应该包含在PUT主体中,但可能会因PUT而改变。话虽如此,我不同意LiorH的观点,即PUT应该导致资源的返还。在PUT之后,我需要GET才能获取更新的资源。
Randolpho

19
@Randolpho REST不需要在PUT上更新整个资源,这不是PATCH的情况吗?
Marco Ciambrone

14
@MarcoCiambrone是的,我同意,我撤回我以前的评论。我已经改变了对REST和PUT的看法-PUT应该始终是幂等的,并且永远不要用于部分更新。除非支持PATCH,否则POST是唯一的选择,在这种情况下,PATCH可能是一个很好的选择。PATCH是一个新动词,但是,某些服务器端框架可能不支持。
Randolpho

2
答案写在rfc7231之前,但第4.3.4节明确指出“ PUT方法要求创建目标资源的状态或将其替换为请求消息有效负载中包含的表示形式所定义的状态”
aaaaaa

3

我认为服务器可能会响应PUT返回内容。如果您使用的响应信封格式允许侧载数据(例如ember-data使用的格式),则还可以包括其他可能已通过数据库触发器修改的对象等。(侧载数据是为了减少#个请求,这似乎是一个优化的好地方。)

如果我只是接受PUT而没有要报告的内容,那么我将使用无正文的状态代码204。如果我要举报,请使用状态码200,并包含一个正文。


2

HTTP / 1.1规范(9.6节)讨论了合适的响应/错误代码。但是,它没有解决响应内容。

您会期望什么?一个简单的HTTP响应代码(200等)对我来说似乎很简单。


是的,但是如果您想检查在PUT或POST之后插入到db中的数据是否真的代表您想要的真实数据该怎么办。如果HTTP可以发回响应主体,那将更好。
tnkh

1
@tnkh您的建议是彻头彻尾的可怕想法。成功更新后,请进行单独的GET调用以实现所需的功能。为了确保性能,如果您在本部门遇到问题,请引入一个缓存层。我们无法通过弄乱“一切皆有可能”的逻辑来解决这些问题。不要搞混“坚实的”和基本的编程原则,这在2020年应该是常识。这是可耻的!
XDS

@XDS我感谢您发表评论的第一部分。但是在那之后不能停止转动我的眼睛。热闹的评论
tnkh

感谢您详细解释为什么您觉得它很有趣。
XDS

2

如果REST API的后端是SQL关系数据库,则

  1. 您应该在每个可以更新的记录中都有RowVersion(以避免丢失更新问题
  2. 您应该始终在PUT之后返回记录的新副本(以获取新的RowVersion)。

如果您不关心丢失的更新,或者想要强制客户在PUT之后立即执行GET,则不要从PUT返回任何内容。


1

Http响应代码201代表“已创建”以及“位置”标头,以指向客户端可以在其中找到新创建的资源的位置。


5
PUT对象不是(也不应该是)新创建的资源
kdazzle

9
@kdazzle PUT当然可以是一个新创建的资源,而且经常是。w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.6
Charlie

3
只是为了更好地解释我的评论。PUT表示将此项放置在此特定位置,替换当前存在的位置(如果适用)。
user1751825 '16

3
是的,“替换当前的内容”是关键词。它应该已经存在并且正在被替换。PUT不应用于创建新资源。
凯文

3
@KevinM就像最新的RFC doc rfc7231一样,它可以创建资源:“ PUT方法要求创建或替换目标资源的状态 [...]”以及您认为PUT无法创建的原因新资源是因为您不一定知道新资源的位置。但是,如果您知道其位置/标识符,则可以在尚不存在的地方创建它。
Leo Lei

0

我在服务中使用了RESTful API,这是我的看法:首先,我们必须达成共识:PUT用于更新创建或获取的资源。

我用Stateless resource和定义了资源Stateful resource

  • 无状态资源对于这些资源,只需返回带有空主体的HttpCode,就足够了。

  • 有状态资源例如:资源的版本。对于此类资源,您必须在要更改版本时提供版本,因此请返回完整资源或将版本返回给客户端,因此客户端无需在更新操作后发送get请求。

但是,对于一个服务或系统,保持它simpleclearlyeasy to use and maintain是最重要的事情。


6
“ PUT用于更新未创建或获取的资源。” -这不是事实,也不是普遍的。根据规范,PUT可以创建资源。清除=遵循众所周知的规格。
伊姆雷·普维尔(ImrePühvel)'18 -10-26

-3

就像一个空的请求正文与GET请求的原始目的保持一致,而空的响应正文与PUT请求的原始目的保持一致。


-3

似乎还可以。。。虽然我认为成功/失败/发布时间/收到的#个字节等基本信息。会更好。

编辑:我一直在考虑数据完整性和/或记录保存;元数据(例如MD5哈希或接收时间的时间戳)对于大型数据文件可能会有所帮助。


1
状态响应标头中的200 OK怎么样?认为这足以说“工作很好,谢谢吗?”
AnthonyWJones

响应头将包含状态码,是的,我们现在正在谈论HTTP :)
AwkwardCoder

-4

理想情况下,它将返回成功/失败响应。


13
但是,不在响应主体中。HTTP状态代码就是这样做的地方。也许如果有错误,则可能会在响应bidy中返回一些扩展的错误信息
The Archetypal Paul

-4

HTTP响应的标头和正文之间存在区别。PUT永远不要返回正文,而必须在标头中返回响应代码。如果成功,选择200,否则选择4xx。没有空返回码之类的东西。为什么要这样做?

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.